Je souhaite insérer des données dans ma table, mais insérer uniquement des données qui n'existent pas déjà dans ma base de données.
Voici mon 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
Et l'erreur est:
Msg 156, niveau 15, état 1, procédure EmailsRecebidosInsert, ligne 11
Syntaxe incorrecte près du mot clé "WHERE".
sql
sql-server
sql-server-2008
stored-procedures
Francisco Carvalho
la source
la source
insert
instruction est toujours une seule transaction. Ce n'est pas comme si SQL Server évalue d'abord la sous-requête, puis à un moment ultérieur, et sans tenir de verrou, continue l'insertion.Réponses:
au lieu de ci-dessous Code
remplacer par
Mise à jour: (merci à @Marc Durdin pour le pointage)
Notez que sous une charge élevée, cela échouera parfois, car une deuxième connexion peut passer le test IF NOT EXISTS avant que la première connexion n'exécute INSERT, c'est-à-dire une condition de concurrence critique. Voir stackoverflow.com/a/3791506/1836776 pour une bonne réponse sur la raison pour laquelle même l'habillage dans une transaction ne résout pas ce problème.
la source
select *
dans ce cas ne fait aucune différence car il est utilisé dans uneEXISTS
clause. SQL Server l'optimisera toujours et le fait depuis des lustres. Depuis que je suis très vieux, j'écris généralement ces requêtes commeEXISTS (SELECT 1 FROM...)
mais ce n'est plus nécessaire.Pour ceux qui recherchent le moyen le plus rapide , j'ai récemment rencontré ces points de référence où apparemment l'utilisation de "INSERT SELECT ... EXCEPT SELECT ..." s'est avérée être la plus rapide pour 50 millions d'enregistrements ou plus.
Voici un exemple de code de l'article (le 3e bloc de code était le plus rapide):
la source
J'utiliserais une fusion:
la source
Essayez le code ci-dessous
la source
La
INSERT
commande n'a pas deWHERE
clause - vous devrez l'écrire comme ceci:la source
J'ai fait la même chose avec SQL Server 2012 et cela a fonctionné
la source
En fonction de votre version (2012?) De SQL Server en plus des IF EXISTS, vous pouvez également utiliser MERGE comme ceci:
la source
SQL différent, même principe. Insérer uniquement si la clause dans laquelle n'existe pas échoue
la source
Comme expliqué dans le code ci-dessous: Exécutez les requêtes ci-dessous et vérifiez vous-même.
Insérez un enregistrement:
Maintenant, essayez à nouveau d'insérer le même enregistrement:
Insérez un enregistrement différent:
la source
Vous pouvez utiliser la
GO
commande. Cela redémarrera l'exécution des instructions SQL après une erreur. Dans mon cas, j'ai quelques 1000 instructions INSERT, où une poignée de ces enregistrements existent déjà dans la base de données, je ne sais pas lesquels. J'ai trouvé qu'après avoir traité quelques 100, l'exécution s'arrête juste avec un message d'erreur qu'il ne peut pasINSERT
car l'enregistrement existe déjà. Assez ennuyeux, mais mettreGO
cela résolu. Ce n'est peut-être pas la solution la plus rapide, mais la vitesse n'était pas mon problème.la source
GO
'est-ce qu'un séparateur de lots? Il n'aide pas à empêcher les enregistrements en double.