MySQL: Wie dekrementiere ich eine vorzeichenlose int-Spalte?

7

Ich habe eine Tabelle mit einer Spalte unsigned int, nennen wir sie col1.

Ich möchte die Spalte um eine Zahl dekrementieren. Wenn der Wert nach dem Dekrementieren kleiner als 1 ist, setzen Sie ihn auf 1. So:

UPDATE `tbl1` SET `col1` = GREATEST(1, `col1`-3);

Dies funktioniert gut, aber wenn col1 0 oder 1 oder 2 ist und ich versuche, -3 zu tun, gibt MySQL einen Fehler aus.

Ich habe dies und das versucht , aber nicht funktioniert.

böseReiko
quelle
Welcher Fehler? Vielleicht verwandt mit UNSIGNED?
Rick James
@ RickJames ist es, ich weiß, weil UNSIGNEDes keine negativen Werte zulässt.
EvilReiko

Antworten:

5

Sie können eine caseKlausel verwenden

update tbl1 set col1 =  (case when col1 <= 3 then 1 else (col1 - 3) end);

Wie @RDFozz beschrieben:

Mit dem im OP aufgelisteten Code muss col1 - 3 berechnet werden, und da es sich um eine vorzeichenlose Ganzzahl handelt, muss das Ergebnis eine vorzeichenlose Ganzzahl sein. Dieser Code verhindert, dass die Berechnung durchgeführt wird, es sei denn, das Ergebnis wäre tatsächlich eine Ganzzahl ohne Vorzeichen.

UPDATE:

Ein anderer möglicher Weg, wie von @kondybas vorgeschlagen

update tbl1 set col1 = IF(col1<=3, 1, col1-3);
Mangel
quelle
2
Hervorragender Punkt. Mit dem aufgelisteten Code des OP col1 - 3muss berechnet werden, und da es sich um eine vorzeichenlose Ganzzahl handelt, muss das Ergebnis eine vorzeichenlose Ganzzahl sein. Ihr alternativer Code verhindert, dass die Berechnung durchgeführt wird, es sei denn, das Ergebnis wäre tatsächlich eine Ganzzahl ohne Vorzeichen.
RDFozz
2
Der andere Ansatz ist die Verwendung der IF()Funktion:SET col1 = IF(col1<3, 1, col1-3)
Kondybas
Die Antworten von DEatTh und @Kondybas sind beide korrekt und funktionieren wie erwartet, obwohl ich die Antwort von Kondybas bevorzuge, da sie mir etwas lesbarer erscheint.
EvilReiko
Um die Bedingung zu erfüllen ..if value after decrement is less than 1 then set it to 1., habe ich <= 3statt< 3
evilReiko
2

Wenn der Wert nach dem Dekrementieren kleiner als 1 ist, setzen Sie ihn auf 1.

Fügen Sie einfach eine WHEREErklärung hinzu

UPDATE tbl1
  SET col1 = col1 - 1
WHERE col1 >= 2;
Evan Carroll
quelle
Gute Antwort. Aber in meinem Fall ist das - 1eine variable Zahl, es kann eine beliebige Zahl sein (-1, -2, -3 usw.). Wie geht das?
EvilReiko
1
UPDATE tbl1 SET col1 = col1 - $var WHERE col1 >= $var + 1;
Evan Carroll
Das funktioniert nicht wie erwartet: Wenn col1 2 ist und ich versuche, -3 wie UPDATE tbl1 SET col1 = col1 - 3 WHERE col1 >= 4;folgt zu machen: dann bleibt col1 als 2, anstatt auf 1 aktualisiert zu werden
evilReiko
2

Noch eine andere Art, diese Katze zu häuten:

UPDATE tbl1 SET col1 = GREATEST(4, col1) - 3

Möglicherweise effizienter:

UPDATE tbl1 SET col1 = GREATEST(4, col1) - 3
    WHERE col1 > 1;
Rick James
quelle
1

Der Mindestwert, den eine unsigned intDose haben kann, ist 0. Sie können sie nur dann auf negativ setzen, wenn sie signiert ist. Sie müssen Logik implementieren, um die Werte in der Spalte zu verarbeiten, damit Sie GREATEST(1, 'col1'-3)nicht gegen die Regel verstoßen. CASE WHENin dieser Anweisung kann genauso gut funktionieren wie das Herausziehen einer gefilterten Teilmenge der Daten mit einer Unterabfrage.

MySQL-Referenz

Stapelüberlaufreferenz

Sie können Ihr vorzeichenloses int auch als signiertes int umwandeln und dann die Arithmetik ausführen.

Stapelüberlaufreferenz beim Gießen auf signiert

Shaulinator
quelle