web-dev-qa-db-fra.com

Comment insérer ou mettre à jour en utilisant une seule requête?

J'ai un test de table ayant des colonnes id dont la clé primaire et auto incrémenté et le nom. Je veux insérer un nouvel enregistrement si annd seulement s'il n'y a pas d'enregistrements. Par exemple

l'entrée est id = 30122 et nom = john

s'il y a des enregistrements avec l'ID 30122, j'ai mis à jour la colonne de nom en john, s'il n'y a pas d'enregistrements, j'ai inséré un nouvel enregistrement.

Je peux faire en utilisant 2 requêtes comme

select * from test where id=30122

s'il a des enregistrements, je peux utiliser update test set name='john' where id=3012

ou s'il n'a pas d'enregistrements, je peux utiliser

insert into test(name) values('john')

Mais je voulais utiliser une seule requête?

Quelqu'un peut-il dire si c'est possible?

29
SpringLearner

Vous pouvez essayer ceci

IF EXISTS(select * from test where id=30122)
   update test set name='john' where id=3012
ELSE
   insert into test(name) values('john');

Une autre approche pour de meilleures performances est

update test set name='john' where id=3012
IF @@ROWCOUNT=0
   insert into test(name) values('john');

et aussi lisez ces mauvaises habitudes pour lancer le préfixe du schéma

46
vijayp

En supposant que SQL Server 2008 ou version ultérieure, vous pouvez utiliser MERGE :

Table

CREATE TABLE dbo.Test
(
    id integer NOT NULL,
    name varchar(30) NULL,

    CONSTRAINT PK_dbo_Test__id
        PRIMARY KEY CLUSTERED (id)
);

Requete

MERGE dbo.Test WITH (SERIALIZABLE) AS T
USING (VALUES (3012, 'john')) AS U (id, name)
    ON U.id = T.id
WHEN MATCHED THEN 
    UPDATE SET T.name = U.name
WHEN NOT MATCHED THEN
    INSERT (id, name) 
    VALUES (U.id, U.name);

L'astuce SERIALIZABLE est requise pour opération correcte sous forte concurrence .

Vous pouvez trouver une comparaison des méthodes courantes de Michael J. Swart ici:

Mythbusting: Solutions simultanées de mise à jour/insertion

17
Evaldas Buinauskas