Ich möchte Daten in meine Tabelle einfügen, aber nur Daten einfügen, die noch nicht in meiner Datenbank vorhanden sind.
Hier ist mein Code:
ALTER PROCEDURE [dbo].[EmailsRecebidosInsert]
(@_DE nvarchar(50),
@_ASSUNTO nvarchar(50),
@_DATA nvarchar(30) )
AS
BEGIN
INSERT INTO EmailsRecebidos (De, Assunto, Data)
VALUES (@_DE, @_ASSUNTO, @_DATA)
WHERE NOT EXISTS ( SELECT * FROM EmailsRecebidos
WHERE De = @_DE
AND Assunto = @_ASSUNTO
AND Data = @_DATA);
END
Und der Fehler ist:
Nachricht 156, Ebene 15, Status 1, Prozedur EmailsRecebidosInsert, Zeile 11
Falsche Syntax in der Nähe des Schlüsselworts 'WHERE'.
sql
sql-server
sql-server-2008
stored-procedures
Francisco Carvalho
quelle
quelle
insert
Anweisung ist immer eine einzelne Transaktion. Es ist nicht so, dass der SQL Server die Unterabfrage zuerst auswertet und dann zu einem späteren Zeitpunkt und ohne eine Sperre zu halten, das Einfügen durchführt.Antworten:
statt unter Code
ersetzen mit
Aktualisiert: (danke an @Marc Durdin für den Hinweis)
Beachten Sie, dass dies unter hoher Last manchmal immer noch fehlschlägt, da eine zweite Verbindung den IF NOT EXISTS-Test bestehen kann, bevor die erste Verbindung das INSERT ausführt, dh eine Race-Bedingung. Unter stackoverflow.com/a/3791506/1836776 finden Sie eine gute Antwort darauf, warum selbst das Einschließen einer Transaktion dies nicht löst.
quelle
select *
in diesem Fall keinen Unterschied, da es in einerEXISTS
Klausel verwendet wird. SQL Server wird es immer optimieren und tut es schon seit Ewigkeiten. Da ich sehr alt bin, schreibe ich diese Abfragen normalerweise als,EXISTS (SELECT 1 FROM...)
aber es wird nicht mehr benötigt.Für diejenigen, die nach dem schnellsten Weg suchen , bin ich kürzlich auf diese Benchmarks gestoßen, bei denen sich die Verwendung von "INSERT SELECT ... EXCEPT SELECT ..." anscheinend als der schnellste für 50 Millionen Datensätze oder mehr herausstellte.
Hier ist ein Beispielcode aus dem Artikel (der 3. Codeblock war der schnellste):
quelle
Ich würde eine Zusammenführung verwenden:
quelle
Versuchen Sie es mit dem folgenden Code
quelle
Der
INSERT
Befehl hat keineWHERE
Klausel - Sie müssen ihn folgendermaßen schreiben:quelle
Ich habe das gleiche mit SQL Server 2012 gemacht und es hat funktioniert
quelle
Abhängig von Ihrer Version (2012?) Von SQL Server können Sie neben IF EXISTS auch MERGE wie folgt verwenden :
quelle
Unterschiedliches SQL, gleiches Prinzip. Nur einfügen, wenn die Klausel in, wo nicht vorhanden, fehlschlägt
quelle
Wie im folgenden Code erläutert: Führen Sie die folgenden Abfragen aus und überprüfen Sie sich.
Datensatz einfügen:
Versuchen Sie nun erneut, denselben Datensatz einzufügen:
Fügen Sie einen anderen Datensatz ein:
quelle
Sie könnten den
GO
Befehl verwenden. Dadurch wird die Ausführung von SQL-Anweisungen nach einem Fehler neu gestartet. In meinem Fall habe ich einige 1000 INSERT-Anweisungen, von denen eine Handvoll dieser Datensätze bereits in der Datenbank vorhanden sind. Ich weiß nur nicht, welche. Ich habe festgestellt, dass nach der Verarbeitung einiger 100 die Ausführung nur mit einer Fehlermeldung beendet wird, die nicht möglich ist,INSERT
da der Datensatz bereits vorhanden ist. Ziemlich nervig, aber das zuGO
lösen. Es ist vielleicht nicht die schnellste Lösung, aber Geschwindigkeit war nicht mein Problem.quelle
GO
ist ein Batch-Separator? Es hilft nicht dabei, doppelte Datensätze zu verhindern.