with ver tutorial stored parametros example ejemplos ejemplo create crear con sql sql-server sql-server-2008 stored-procedures

ver - stored procedure sql tutorial



Insertar SQL Server si no existe (8)

Quiero insertar datos en mi tabla, ¡pero solo inserto que no existe en mi DB!

aquí está mi código:

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

Y el error es:

Msg 156, nivel 15, estado 1, correos electrónicos de procedimientoRecebidosInsert, línea 11
Sintaxis incorrecta cerca de la palabra clave ''WHERE''.


Dependiendo de su versión (2012?) De SQL Server además de IF EXISTS, también puede usar MERGE como MERGE :

ALTER PROCEDURE [dbo].[EmailsRecebidosInsert] ( @_DE nvarchar(50) , @_ASSUNTO nvarchar(50) , @_DATA nvarchar(30)) AS BEGIN MERGE [dbo].[EmailsRecebidos] [Target] USING (VALUES (@_DE, @_ASSUNTO, @_DATA)) [Source]([De], [Assunto], [Data]) ON [Target].[De] = [Source].[De] AND [Target].[Assunto] = [Source].[Assunto] AND [Target].[Data] = [Source].[Data] WHEN NOT MATCHED THEN INSERT ([De], [Assunto], [Data]) VALUES ([Source].[De], [Source].[Assunto], [Source].[Data]); END


El comando INSERT no tiene una cláusula WHERE ; tendrás que escribirlo así:

ALTER PROCEDURE [dbo].[EmailsRecebidosInsert] (@_DE nvarchar(50), @_ASSUNTO nvarchar(50), @_DATA nvarchar(30) ) AS BEGIN IF NOT EXISTS (SELECT * FROM EmailsRecebidos WHERE De = @_DE AND Assunto = @_ASSUNTO AND Data = @_DATA) BEGIN INSERT INTO EmailsRecebidos (De, Assunto, Data) VALUES (@_DE, @_ASSUNTO, @_DATA) END END


Hice lo mismo con SQL Server 2012 y funcionó

Insert into #table1 With (ROWLOCK) (Id, studentId, name) SELECT ''18769'', ''2'', ''Alex'' WHERE not exists (select * from #table1 where Id = ''18769'' and studentId = ''2'')


Para aquellos que buscan la manera más rápida , recientemente encontré estos puntos de referencia donde aparentemente el uso de "INSERT SELECT ... EXCEPT SELECT ..." resultó ser el más rápido para 50 millones de registros o más.

Aquí hay un código de muestra del artículo (el tercer bloque de código fue el más rápido):

INSERT INTO #table1 (Id, guidd, TimeAdded, ExtraData) SELECT Id, guidd, TimeAdded, ExtraData FROM #table2 WHERE NOT EXISTS (Select Id, guidd From #table1 WHERE #table1.id = #table2.id) ----------------------------------- MERGE #table1 as [Target] USING (select Id, guidd, TimeAdded, ExtraData from #table2) as [Source] (id, guidd, TimeAdded, ExtraData) on [Target].id =[Source].id WHEN NOT MATCHED THEN INSERT (id, guidd, TimeAdded, ExtraData) VALUES ([Source].id, [Source].guidd, [Source].TimeAdded, [Source].ExtraData); ------------------------------ INSERT INTO #table1 (id, guidd, TimeAdded, ExtraData) SELECT id, guidd, TimeAdded, ExtraData from #table2 EXCEPT SELECT id, guidd, TimeAdded, ExtraData from #table1 ------------------------------ INSERT INTO #table1 (id, guidd, TimeAdded, ExtraData) SELECT #table2.id, #table2.guidd, #table2.TimeAdded, #table2.ExtraData FROM #table2 LEFT JOIN #table1 on #table1.id = #table2.id WHERE #table1.id is null


Podría usar el comando GO. Eso reiniciará la ejecución de sentencias SQL después de un error. En mi caso, tengo unas 1000 declaraciones INSERT, donde ya existen un puñado de esos registros en la base de datos, pero no sé cuáles. Descubrí que después de procesar unos 100, la ejecución simplemente se detiene con un mensaje de error que no puede INSERTAR porque el registro ya existe. Muy molesto, pero poner un GO resolvió esto. Puede que no sea la solución más rápida, pero la velocidad no era mi problema.

GO INSERT INTO mytable (C1,C2,C3) VALUES(1,2,3) GO INSERT INTO mytable (C1,C2,C3) VALUES(4,5,6) etc ...


Pruebe el código siguiente

ALTER PROCEDURE [dbo].[EmailsRecebidosInsert] (@_DE nvarchar(50), @_ASSUNTO nvarchar(50), @_DATA nvarchar(30) ) AS BEGIN INSERT INTO EmailsRecebidos (De, Assunto, Data) select @_DE, @_ASSUNTO, @_DATA EXCEPT SELECT De, Assunto, Data from EmailsRecebidos END


Yo usaría una fusión:

create PROCEDURE [dbo].[EmailsRecebidosInsert] (@_DE nvarchar(50), @_ASSUNTO nvarchar(50), @_DATA nvarchar(30) ) AS BEGIN with data as (select @_DE as de, @_ASSUNTO as assunto, @_DATA as data) merge EmailsRecebidos t using data s on s.de = t.de and s.assunte = t.assunto and s.data = t.data when not matched by target then insert (de, assunto, data) values (s.de, s.assunto, s.data); END


en lugar de debajo del código

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

reemplazar con

BEGIN IF NOT EXISTS (SELECT * FROM EmailsRecebidos WHERE De = @_DE AND Assunto = @_ASSUNTO AND Data = @_DATA) BEGIN INSERT INTO EmailsRecebidos (De, Assunto, Data) VALUES (@_DE, @_ASSUNTO, @_DATA) END END

Actualizado: (gracias a @Marc Durdin por señalar)

Tenga en cuenta que a una carga alta, esto a veces fallará, porque una segunda conexión puede pasar la prueba IF NOT EXISTS antes de que la primera conexión ejecute el INSERT, es decir, una condición de carrera. Consulte .com/a/3791506/1836776 para obtener una buena respuesta sobre por qué incluso el ajuste en una transacción no resuelve esto.