SQL come aumentare o diminuire uno per una colonna int in un comando


119

Ho una tabella Ordini che ha una colonna Quantità. Durante il check-in o il check-out, dobbiamo aggiornare la colonna Quantità di uno. C'è un modo per farlo in un'azione o dobbiamo ottenere il valore esistente e quindi aggiungerne o meno uno sopra?

Un'altra domanda è quando inseriamo una nuova riga, dobbiamo controllare se gli stessi dati esistono e poi inserirli in caso contrario, che sono due passaggi, o c'è un modo migliore per farlo?

Grazie,

Risposte:


250

Per rispondere alla prima:

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

Per rispondere alla seconda:

Ci sono diversi modi per farlo. Poiché non hai specificato un database, assumerò MySQL.

  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

Entrambi possono gestire la tua domanda. Tuttavia, la prima sintassi consente una maggiore flessibilità per aggiornare il record piuttosto che sostituirlo semplicemente (come fa la seconda).

Tieni presente che affinché entrambi possano esistere, deve essere definita una chiave UNICA ...


32
Dato che non hai specificato un database, dovresti davvero assumere l'SQL standard.
paxdiablo

12

La risposta in un unico passaggio alla prima domanda è usare qualcosa come:

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

Questo è un modo molto semplice per farlo.

Per quanto riguarda la seconda domanda, non dovresti aver bisogno di ricorrere a ginnastica SQL specifica per DBMS (come UPSERT) per ottenere il risultato desiderato. Esiste un metodo standard per eseguire l'aggiornamento o l'inserimento che non richiede un DBMS specifico.

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

Cioè, provi prima a fare la creazione. Se è già presente, ignora l'errore. Altrimenti lo crei con un valore 0.

Quindi esegui l'aggiornamento che funzionerà correttamente indipendentemente dal fatto che:

  • la riga esisteva originariamente.
  • qualcuno l'ha aggiornato tra l'inserimento e l'aggiornamento.

Non è una singola istruzione e tuttavia, abbastanza sorprendentemente, è il modo in cui lo facciamo con successo da molto tempo.


4

Se la mia comprensione è corretta, gli aggiornamenti dovrebbero essere piuttosto semplici. Vorrei solo fare quanto segue.

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

Potresti aver bisogno di filtri aggiuntivi per aggiornare solo una singola riga invece di tutte le righe.

Per gli inserti, puoi memorizzare nella cache un ID univoco correlato al tuo record localmente e controllare questa cache e decidere se inserire o meno. L'approccio alternativo consiste nell'inserire e controllare sempre l'errore di violazione PK e ignorarlo poiché si tratta di un inserimento ridondante.


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

Per quanto ne so, non esiste un supporto integrato per INSERT-OR-UPDATE in SQL. Suggerisco di creare una stored procedure o utilizzare una query condizionale per ottenere ciò. Qui puoi trovare una raccolta di soluzioni per diversi database.


Potresti ricevere un errore di sintassi lanciando la parola riservata ORDER in questo modo ...
gahooa

0

per rispondere alla seconda:

rendi la colonna univoca e cattura l'eccezione se è impostata sullo stesso valore.


0

@dotjoe È più economico aggiornare e controllare @@ rowcount, fare un inserimento dopo il fatto.

Le eccezioni sono costose e gli aggiornamenti sono più frequenti

Suggerimento: se vuoi essere super performante nel tuo DAL, fai passare il front-end in un ID univoco per la riga da aggiornare, se null inserire.

I DAL dovrebbero essere CRUD e non è necessario preoccuparsi di essere apolidi.

Se lo rendi senza stato, con buoni indici, non vedrai una differenza con la seguente istruzione SQL vs 1. IF (seleziona top 1 * form x dove PK = @ ID) Inserisci altro aggiornamento

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.