SQL, wie eine für eine int-Spalte in einem Befehl erhöht oder verringert wird

119

Ich habe eine Auftragstabelle mit einer Mengenspalte. Beim Ein- und Auschecken müssen wir diese Mengen-Spalte um eins aktualisieren. Gibt es eine Möglichkeit, dies in einer Aktion zu tun, oder müssen wir den vorhandenen Wert abrufen und dann einen hinzufügen oder minus hinzufügen?

Eine andere Frage ist, wenn wir eine neue Zeile einfügen. Müssen wir überprüfen, ob dieselben Daten vorhanden sind, und dann einfügen, wenn nicht, was zwei Schritte sind, oder gibt es einen besseren Weg, dies zu tun?

Vielen Dank,

5YrsLaterDBA
quelle

Antworten:

250

Um das erste zu beantworten:

UPDATE Orders SET Quantity = Quantity + 1 WHERE ...

Um die zweite zu beantworten:

Es gibt verschiedene Möglichkeiten, dies zu tun. Da Sie keine Datenbank angegeben haben, gehe ich von MySQL aus.

  1. INSERT INTO table SET x=1, y=2 ON DUPLICATE KEY UPDATE x=x+1, y=y+2
  2. REPLACE INTO table SET x=1, y=2

Beide können Ihre Frage beantworten. Die erste Syntax ermöglicht jedoch mehr Flexibilität beim Aktualisieren des Datensatzes, anstatt ihn nur zu ersetzen (wie bei der zweiten).

Denken Sie daran, dass für beide ein EINZIGARTIGER Schlüssel definiert sein muss ...

gahooa
quelle
32
Da Sie keine Datenbank angegeben haben, sollten Sie wirklich Standard-SQL annehmen.
Paxdiablo
12

Die einstufige Antwort auf die erste Frage lautet:

update TBL set CLM = CLM + 1 where key = 'KEY'

Das ist eine Art Einzelanweisung.

Bei der zweiten Frage sollten Sie nicht auf DBMS-spezifische SQL-Gymnastik (wie UPSERT) zurückgreifen müssen , um das gewünschte Ergebnis zu erzielen. Es gibt eine Standardmethode zum Aktualisieren oder Einfügen, für die kein bestimmtes DBMS erforderlich ist.

try:
    insert into TBL (key,val) values ('xyz',0)
catch:
    do nothing
update TBL set val = val + 1 where key = 'xyz'

Das heißt, Sie versuchen zuerst, die Erstellung durchzuführen. Wenn es bereits vorhanden ist, ignorieren Sie den Fehler. Andernfalls erstellen Sie es mit einem 0-Wert.

Führen Sie dann das Update durch, das ordnungsgemäß funktioniert, unabhängig davon, ob:

  • Die Zeile existierte ursprünglich.
  • jemand hat es zwischen Ihrer Einfügung und Aktualisierung aktualisiert.

Es ist keine einzige Anweisung, und doch machen wir es überraschenderweise schon lange so erfolgreich.

paxdiablo
quelle
4

Wenn mein Verständnis korrekt ist, sollten Updates ziemlich einfach sein. Ich würde nur folgendes tun.

UPDATE TABLE SET QUANTITY = QUANTITY + 1 and
UPDATE TABLE SET QUANTITY = QUANTITY - 1 where QUANTITY > 0

Möglicherweise benötigen Sie zusätzliche Filter, um nur eine einzelne Zeile anstelle aller Zeilen zu aktualisieren.

Bei Einfügungen können Sie eine eindeutige ID für Ihren Datensatz lokal zwischenspeichern und anhand dieses Caches prüfen, ob eingefügt werden soll oder nicht. Der alternative Ansatz besteht darin, immer einen PK-Verstoßfehler einzufügen und zu überprüfen und zu ignorieren, da dies ein redundantes Einfügen ist.

msvcyc
quelle
4
UPDATE Orders Order
SET Order.Quantity =  Order.Quantity - 1
WHERE SomeCondition(Order)

Soweit ich weiß, gibt es keine integrierte Unterstützung für INSERT-OR-UPDATE in SQL. Ich schlage vor, eine gespeicherte Prozedur zu erstellen oder eine bedingte Abfrage zu verwenden, um dies zu erreichen. Hier finden Sie eine Sammlung von Lösungen für verschiedene Datenbanken.

Daniel Brückner
quelle
Sie könnten einen Syntaxfehler bekommen, der das reservierte Wort ORDER so
herumwirft
0

um die zweite zu beantworten:

Machen Sie die Spalte eindeutig und fangen Sie die Ausnahme ab, wenn sie auf denselben Wert gesetzt ist.

dotjoe
quelle
0

@dotjoe Es ist billiger, @@ rowcount zu aktualisieren und zu überprüfen, danach eine Einfügung vorzunehmen.

Ausnahmen sind teuer und Updates sind häufiger

Vorschlag: Wenn Sie in Ihrem DAL überdurchschnittlich leistungsfähig sein möchten, geben Sie dem Front-End-Pass eine eindeutige ID für die zu aktualisierende Zeile, wenn Null eingefügt wird.

Die DALs sollten CRUD sein und sich keine Sorgen machen müssen, dass sie staatenlos sind.

Wenn Sie es zustandslos machen, sehen Sie bei guten Indizes keinen Unterschied mit der folgenden SQL vs 1-Anweisung. IF (wählen Sie die oberste 1 * Form x aus, wobei PK = @ ID) Fügen Sie ein anderes Update ein

Brian Chandley
quelle