Wie füge ich eine einzelne Abfrage ein oder aktualisiere sie?


25

Ich habe einen Tabellentest mit Spalten-ID, die den Primärschlüssel und automatisch erhöht und benennt. Ich möchte nur dann einen neuen Datensatz einfügen, wenn keine Datensätze vorhanden sind. Zum Beispiel

Eingabe ist id = 30122 und name = john

Wenn es Datensätze mit der ID 30122 gibt, habe ich die Namensspalte auf John aktualisiert. Wenn es keine Datensätze gibt, habe ich einen neuen Datensatz eingefügt.

Ich kann mit 2 Abfragen wie

select * from test where id=30122

wenn es einige aufzeichnungen hat dann kann ich verwenden update test set name='john' where id=3012

oder wenn es keine aufzeichnungen gibt dann kann ich verwenden

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

Aber ich wollte eine einzelne Abfrage verwenden?

Kann jemand sagen, ob es möglich ist?


1
But I wanted to use single query?Warum?
Aaron Bertrand

@AaronBertrand Mein Backend verwendet java.So entwickelt Wenn ich 2 quries dann muss ich die DB 2 times.So schlagen , wenn es mit einer einzigen Abfrage durchgeführt werden kann , warum dann zwei Abfragen verwenden
SpringLearner

1
Java unterstützt keine gespeicherte Prozedur oder einen einzelnen Stapel mit zwei Anweisungen, die nur einen Treffer in der Datenbank erfordern?
Aaron Bertrand

@AaronBertrand könntest du ein Beispiel geben, wie du damit mit SQL Server 2008 oder später umgehen würdest?
eaglei22

1
@ eaglei22 Ich würde das 2. Beispiel in der Antwort von vijayp unten verwenden. Ich würde noch MERGEin keiner Version wählen , auch nicht SQL Server 2019. Einige Hintergründe dazu hier .
Aaron Bertrand

Antworten:


41

Sie können dies versuchen

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

Ein anderer Ansatz für eine bessere Leistung ist

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

und lesen Sie auch diese schlechten Gewohnheiten, um auf Schema-Präfix zu treten


4
Das erste Beispiel ist verschwenderisch und kann oft zu Deadlocks führen - ich würde es überhaupt nicht vorschlagen.
Aaron Bertrand

@ AaronBertrand Pflege zu erarbeiten? Danke
Hexo

5
@ SlapY Sicher, im ersten Beispiel sagen Sie: "Hey, SQL Server, gibt es eine Zeile mit dieser ID?" SQL Server sucht nach der Zeile, möglicherweise mithilfe eines Scans, und gibt dann die Antwort zurück. "Warum, ja, Benutzer, ich habe eine Zeile mit dieser ID!" Dann sagen Sie: "Okay, SQL Server, suchen Sie diese Zeile erneut , aber aktualisieren Sie sie dieses Mal!" Sehen Sie, wie verschwenderisch es ist, zweimal zu suchen oder zu scannen? Können Sie sich vorstellen, was passiert, wenn ein anderer Benutzer SQL Server dieselbe Frage zum Vorhandensein einer Zeile stellt, bevor Sie etwas dagegen unternehmen?
Aaron Bertrand

Danke, ich verstehe nur nicht, warum der erste zum Stillstand droht, der zweite nicht? Beide bestehen aus mehreren Anweisungen, die abgefangen werden können, wenn sie nicht mit voller Sperre ausgeführt werden. Liege ich falsch?
Hexo

2
@ 0x25b3 Es ist nicht so, dass einer von Deadlocks bedroht ist und der andere nicht, sondern dass das erste Beispiel viel anfälliger für sie ist. In beiden Fällen sollten Sie eine vollständige und ordnungsgemäße Transaktion abschließen, aber die Leute tun dies nicht.
Aaron Bertrand

17

Unter der Annahme von SQL Server 2008 oder höher können Sie Folgendes verwenden MERGE:

Tabelle

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

    CONSTRAINT PK_dbo_Test__id
        PRIMARY KEY CLUSTERED (id)
);

Abfrage

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);

Der SERIALIZABLEHinweis ist für den korrekten Betrieb bei hoher Parallelität erforderlich .

Einen Vergleich der gängigen Methoden von Michael J. Swart finden Sie hier:

Mythbusting: Concurrent Update / Insert Solutions


8
Merge hat einige Probleme .
vonPryz,

die mythos-sprengende verbindung dort ist exzellent. Schön!
JonnyRaa
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.