web-dev-qa-db-fra.com

Comment INSÉRER un enregistrement ou UPDATE s'il existe déjà?

J'ai une table avec des colonnes record_id (auto inc), sender, sent_time et status.

Dans le cas où il n'y a pas d'enregistrement d'un expéditeur particulier, par exemple "expéditeur1", je dois INSÉRER un nouvel enregistrement sinon je dois METTRE À JOUR l'enregistrement existant qui appartient à "utilisateur1".

Donc, s'il n'y a pas d'enregistrement déjà stocké, j'exécuterais

# record_id is AUTO_INCREMENT field
INSERT INTO messages (sender, sent_time, status)
VALUES (@sender, time, @status)

Sinon, j'exécuterais l'instruction UPDATE.

Quoi qu'il en soit .. est-ce que quelqu'un sait comment combiner ces deux instructions pour insérer un nouvel enregistrement s'il n'existe aucun enregistrement dont la valeur de l'expéditeur du champ est "utilisateur1", sinon mettre à jour l'enregistrement existant?

31
Niko Gamulin

MySQL supporte la syntaxe insert-on-duplicate , par exemple:

INSERT INTO table (key,col1) VALUES (1,2)
  ON DUPLICATE KEY UPDATE col1 = 2;
47
Andomar

Si vous avez des contraintes solides sur la table, vous pouvez également utiliser le REPLACE INTO pour cela. Voici un extrait de MySQL:

REPLACE fonctionne exactement comme INSERT, sauf que si une ancienne ligne de la table a la même valeur qu'une nouvelle ligne pour une clé PRIMARY KEY ou un index UNIQUE, l'ancienne ligne est supprimée avant que la nouvelle ligne ne soit insérée.

La syntaxe est fondamentalement la même que INSERT INTO, remplacez simplement INSERT par REPLACE.

INSERT INTO messages (sender, sent_time, status) VALUES (@sender, time, @status)

serait alors

REPLACE INTO messages (sender, sent_time, status) VALUES (@sender, time, @status)

Notez qu'il s'agit d'une commande spécifique à MySQL qui ne figure pas dans les autres bases de données. Gardez donc à l'esprit la portabilité.

12
BalusC

Comme d'autres l'ont mentionné, vous devriez utiliser "insérer ... sur la mise à jour de clé dupliquée", parfois appelée "upsert". Toutefois, dans votre cas spécifique, vous ne souhaitez pas utiliser une valeur statique dans la mise à jour, mais plutôt les valeurs que vous transmettez à la clause values ​​de l'instruction insert.

Plus précisément, je pense que vous souhaitez mettre à jour deux colonnes si la ligne existe déjà:

1) sent_time
2) status

Pour ce faire, utilisez une instruction "upsert" comme celle-ci (en utilisant votre exemple):

INSERT INTO messages (sender, sent_time, status) 
VALUES (@sender, time, @status)
ON DUPLICATE KEY UPDATE 
  sent_time = values(sent_time),
  status = values(status);
3
Ike Walker

Départ "Insérer lors de la mise à jour des clés en double" .

INSERT INTO table (a,b,c) VALUES (1,2,3)
  ON DUPLICATE KEY UPDATE c=c+1;

UPDATE table SET c=c+1 WHERE a=1;
2
Sampson

Une des options est d'utiliser une syntaxe de mise à jour en double

http://dev.mysql.com/doc/refman/5.1/en/insert-on-duplicate.html

D’autres options consiste à sélectionner si un enregistrement existe, puis à insérer/mettre à jour en conséquence. Notez que si vous effectuez une transaction, select ne mettra pas explicitement fin à la transaction, vous pouvez donc l'utiliser en toute sécurité.

1
Julian Davchev
use merge statement :

merge into T1
          using T2
          on (T1.ID = T2.ID)
    when  matched
    then  update set  
                      T1.Name = T2.Name
    when  not matched
    then  insert values (T2.ID,T2.Name);
0
Rajeev Kumar Mehta