Quiero insertar datos en mi tabla, pero insertar solo datos que no existen en mi base de datos.
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, Procedimiento EmailsRecebidosInsert, Línea 11
Sintaxis incorrecta cerca de la palabra clave 'WHERE'.
sql
sql-server
sql-server-2008
stored-procedures
Francisco Carvalho
fuente
fuente
insert
declaración es siempre una sola transacción. No es como si el SQL Server evalúa la subconsulta primero y luego en algún momento posterior, y sin mantener un bloqueo, continúa con la inserción.Respuestas:
en lugar de debajo del código
reemplazar con
Actualizado: (gracias a @Marc Durdin por señalar)
Tenga en cuenta que bajo una carga alta, esto a veces fallará, porque una segunda conexión puede pasar la prueba SI NO EXISTE antes de que la primera conexión ejecute INSERT, es decir, una condición de carrera. Consulte stackoverflow.com/a/3791506/1836776 para obtener una buena respuesta sobre por qué incluso concluir una transacción no resuelve esto.
fuente
select *
en este caso no hace ninguna diferencia porque se está usando en unaEXISTS
cláusula. SQL Server siempre lo optimizará y lo ha estado haciendo durante años. Como soy muy viejo, generalmente escribo estas consultas,EXISTS (SELECT 1 FROM...)
pero ya no es necesario.Para aquellos que buscan la forma más rápida , recientemente me encontré con estos puntos de referencia donde aparentemente usar "INSERTAR SELECCIONAR ... EXCEPTO SELECCIONAR ..." 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):
fuente
Yo usaría una fusión:
fuente
Prueba el siguiente código
fuente
El
INSERT
comando no tiene unaWHERE
cláusula, tendrá que escribirlo así:fuente
Hice lo mismo con SQL Server 2012 y funcionó
fuente
Dependiendo de su versión (2012?) De SQL Server aparte de IF EXISTS, también puede usar MERGE de esta manera:
fuente
SQL diferente, mismo principio. Solo inserte si la cláusula en donde no existe falla
fuente
Como se explica en el siguiente código: Ejecute las consultas a continuación y verifíquese.
Insertar un registro:
Ahora, intente insertar el mismo registro nuevamente:
Insertar un registro diferente:
fuente
Podrías usar el
GO
comando. Eso reiniciará la ejecución de las instrucciones SQL después de un error. En mi caso, tengo unas 1000 instrucciones INSERT, donde ya existen algunos de esos registros en la base de datos, simplemente 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 puedeINSERT
porque el registro ya existe. Bastante molesto, pero poniendo unGO
resolviendo esto. Puede que no sea la solución más rápida, pero la velocidad no fue mi problema.fuente
GO
es un separador de lotes? No ayuda a prevenir registros duplicados.