SQL comment augmenter ou diminuer un pour une colonne int en une seule commande

119

J'ai une table Commandes qui a une colonne Quantité. Lors de l'enregistrement ou du départ, nous devons mettre à jour cette colonne Quantité par un. Y a-t-il un moyen de le faire en une seule action ou nous devons obtenir la valeur existante et ensuite en ajouter ou en réduire une?

Une autre question est lorsque nous insérons une nouvelle ligne, devons-nous vérifier si les mêmes données existent, puis insérer sinon, ce qui est en deux étapes, ou y a-t-il une meilleure façon de le faire?

Merci,

5 ans plus tardDBA
la source

Réponses:

250

Pour répondre à la première:

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

Pour répondre à la seconde:

Il y a plusieurs moyens de le faire. Puisque vous n'avez pas spécifié de base de données, je suppose que 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

Ils peuvent tous les deux répondre à votre question. Cependant, la première syntaxe offre plus de flexibilité pour mettre à jour l'enregistrement plutôt que de simplement le remplacer (comme le fait la seconde).

Gardez à l'esprit que pour que les deux existent, il doit y avoir une clé UNIQUE définie ...

gahooa
la source
32
Puisque vous n'avez pas spécifié de base de données, vous devez vraiment assumer le SQL standard.
paxdiablo
12

La réponse en une seule étape à la première question est d'utiliser quelque chose comme:

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

C'est en grande partie une manière à instruction unique de le faire.

En ce qui concerne la deuxième question, vous ne devriez pas avoir besoin de recourir à la gymnastique SQL spécifique au SGBD (comme UPSERT) pour obtenir le résultat souhaité. Il existe une méthode standard pour effectuer une mise à jour ou une insertion qui ne nécessite pas de SGBD spécifique.

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

Autrement dit, vous essayez de faire la création en premier. S'il est déjà là, ignorez l'erreur. Sinon, vous le créez avec une valeur 0.

Ensuite, faites la mise à jour qui fonctionnera correctement que ce soit ou non:

  • la ligne existait à l'origine.
  • quelqu'un l'a mis à jour entre votre insertion et la mise à jour.

Ce n'est pas une seule instruction et pourtant, assez étonnamment, c'est la façon dont nous le faisons avec succès depuis longtemps.

paxdiablo
la source
4

Si ma compréhension est correcte, les mises à jour devraient être assez simples. Je ferais juste ce qui suit.

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

Vous aurez peut-être besoin de filtres supplémentaires pour ne mettre à jour qu'une seule ligne au lieu de toutes les lignes.

Pour les insertions, vous pouvez mettre en cache localement un identifiant unique lié à votre enregistrement et vérifier par rapport à ce cache et décider de l'insérer ou non. L'approche alternative consiste à toujours insérer et vérifier l'erreur de violation PK et à l'ignorer car il s'agit d'une insertion redondante.

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

Autant que je sache, il n'y a pas de support intégré pour INSERT-OR-UPDATE dans SQL. Je suggère de créer une procédure stockée ou d'utiliser une requête conditionnelle pour y parvenir. Ici vous trouverez une collection de solutions pour différentes bases de données.

Daniel Brückner
la source
Vous pourriez obtenir une erreur de syntaxe en lançant le mot réservé ORDER comme ça ...
gahooa
0

pour répondre à la seconde:

rendez la colonne unique et interceptez l'exception si elle est définie sur la même valeur.

dotjoe
la source
0

@dotjoe Il est moins coûteux de mettre à jour et de vérifier @@ rowcount, faire une insertion après coup.

Les exceptions sont chères et les mises à jour sont plus fréquentes

Suggestion: Si vous voulez être ultra performant dans votre DAL, faites passer le frontal dans un ID unique pour la ligne à mettre à jour, si l'insertion est nulle.

Les DAL doivent être CRUD et ne pas avoir à craindre d'être apatrides.

Si vous le rendez sans état, avec de bons index, vous ne verrez pas de différence avec l'instruction SQL vs 1 suivante. IF (sélectionnez top 1 * form x où PK = @ ID) Insérer autre mise à jour

Brian Chandley
la source