69 votes

Le serveur SQL offre-t-il quelque chose comme l'UPDATE ON DUPLICATE KEY de MySQL ?

Dans MySQL, si vous spécifiez SUR LA MISE À JOUR DE LA CLÉ DUPLIQUÉE et qu'une ligne est insérée qui entraînerait une valeur en double dans un index UNIQUE ou PRIMARY KEY, une mise à jour de l'ancienne ligne est effectuée. Par exemple, si la colonne a est déclarée comme UNIQUE et contient la valeur 1, les deux instructions suivantes ont un effet identique :

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;

Je ne crois pas avoir rencontré une telle chose en T-SQL. Le serveur SQL offre-t-il quelque chose de comparable à la fonction ON DUPLICATE KEY UPDATE de MySQL ?

0 votes

Vous pouvez le simuler avec une procédure stockée. Je n'ai pas le code exact dans ma tête.

0 votes

@Robert Harvey - J'ai toujours effectué une opération en vérifiant si la ligne existe. Si oui, il faut alors effectuer une mise à jour ou insérer une nouvelle ligne. Est-ce que c'est ce que vous pensiez également ?

51voto

Il n'y a pas d'équivalent de DUPLICATE KEY UPDATE, mais MERGE et WHEN MATCHED peuvent vous convenir.

Insertion, mise à jour et suppression de données à l'aide de MERGE

15 votes

Sachez simplement que MERGE n'est pas à l'abri d'une collision d'insertions à fort taux de change. Vous pouvez consulter doit utiliser WITH (UPDLOCK, HOLDLOCK) pour que les fusions n'entrent pas en collision. Certains systèmes à très haute vitesse de transaction par seconde utilisent une stratégie différente où les verrous ne sont pas utilisés, mais où toute erreur est piégée et ensuite convertie en une mise à jour.

51voto

IvanD Points 581

J'ai été surpris de constater qu'aucune des réponses de cette page ne contenait un exemple de requête réelle, alors voilà :

Un exemple plus complexe d'insertion de données puis de traitement des doublons

MERGE
INTO MyBigDB.dbo.METER_DATA WITH (HOLDLOCK) AS target
USING (SELECT
    77748 AS rtu_id
   ,'12B096876' AS meter_id
   ,56112 AS meter_reading
   ,'20150602 00:20:11' AS local_time) AS source
(rtu_id, meter_id, meter_reading, time_local)
ON (target.rtu_id = source.rtu_id
  AND target.time_local = source.time_local)
WHEN MATCHED
  THEN UPDATE
      SET meter_id = '12B096876'
         ,meter_reading = 56112
WHEN NOT MATCHED
  THEN INSERT (rtu_id, meter_id, meter_reading, time_local)
      VALUES (77748, '12B096876', 56112, '20150602 00:20:11');

16 votes

Vous êtes, monsieur, un sauveur de vie. Je déteste vraiment les documentations de microsoft... elles donnent toujours tous les exemples sauf ceux qui sont utilisés le plus fréquemment.

0 votes

'MERGE INTO MyFancyTableName WITH (HOLDLOCK) AS target USING (SELECT :id AS id, :lastaccess AS lastaccess ) AS source (id,lastaccess) ON (target.id = source.id) WHEN MATCHED THEN UPDATE SET lastaccess = :lastaccess2 WHEN NOT MATCHED THEN INSERT (id, lastaccess) VALUES (:id2, :lastaccess3);' Dois-je afficher les deux variables dans le USING ou seulement le id suffisent-ils ?

0 votes

Merci pour la référence à la commande Merge. Je dois préciser que, dans les déclarations comparées, vous utilisez les mêmes valeurs que celles que vous avez définies comme source. Ainsi, si vous souhaitez mettre à jour un grand nombre d'enregistrements, vous devriez attribuer la valeur source de la manière suivante :

4voto

mesutuk Points 12

Vous pouvez essayer dans l'autre sens. Cela fait plus ou moins la même chose.

UPDATE tablename 
SET    field1 = 'Test1', 
       field2 = 'Test2' 
WHERE  id = 1 

IF @@ROWCOUNT = 0 
  INSERT INTO tablename 
              (id, 
               field1, 
               field2) 
  VALUES      (1, 
               'Test1', 
               'Test2')

3voto

shahkalpesh Points 21553

SQL Server 2008 dispose de cette fonctionnalité, dans le cadre de TSQL.
Voir la documentation sur l'instruction MERGE ici - http://msdn.microsoft.com/en-us/library/bb510625.aspx

1 votes

Sachez simplement que MERGE n'est pas à l'abri des collisions d'insertions à haute fréquence. Vous devez utiliser WITH (UPDLOCK, HOLDLOCK) pour que la fusion n'entre pas en collision. Certains systèmes à taux de transaction par seconde très élevé utilisent une stratégie différente où les verrous ne sont pas utilisés, mais où toute erreur est piégée et convertie en mise à jour.

1voto

Tetraneutron Points 8494

À partir de SQL Server 2000, il existe un concept de remplacement des déclencheurs, qui permet d'accomplir la fonctionnalité souhaitée - même si un méchant déclencheur se cache dans les coulisses.

Vérifiez la section "Insérer ou mettre à jour ?"

http://msdn.microsoft.com/en-us/library/aa224818(SQL.80).aspx

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X