Я хочу вставить данные в мою таблицу, но вставить только те данные, которых еще нет в моей базе данных.
Вот мой код:
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
И ошибка:
Сообщение 156, уровень 15, состояние 1, процедура EmailsRecebidosInsert, строка 11
Неверный синтаксис рядом с ключевым словом «ГДЕ».
sql
sql-server
sql-server-2008
stored-procedures
Франсиско Карвалью
источник
источник
insert
оператор - это всегда одна транзакция. Дело не в том, что SQL Server сначала оценивает подзапрос, а затем в какой-то более поздний момент и, не удерживая блокировку, продолжает выполнять вставку.Ответы:
вместо приведенного ниже кода
заменить
Обновлено: (спасибо @Marc Durdin за указание)
Обратите внимание, что при высокой нагрузке это все равно иногда будет выходить из строя, поскольку второе соединение может пройти тест IF NOT EXISTS до того, как первое соединение выполнит INSERT, то есть условие гонки. См. Stackoverflow.com/a/3791506/1836776 для хорошего ответа о том, почему даже перенос в транзакцию не решает эту проблему.
источник
select *
в этом случае не имеет значения, потому что он используется вEXISTS
предложении. SQL Server всегда будет оптимизировать это и делал это целую вечность. Поскольку я очень старый, я обычно пишу эти запросы как,EXISTS (SELECT 1 FROM...)
но это больше не нужно.Для тех, кто ищет самый быстрый способ , я недавно наткнулся на эти тесты, где использование INSERT SELECT ... EXCEPT SELECT ... оказалось, очевидно, самым быстрым для 50 миллионов записей или более.
Вот пример кода из статьи (3-й блок кода был самым быстрым):
источник
Я бы использовал слияние:
источник
Попробуйте код ниже
источник
У
INSERT
команды нетWHERE
предложения - вам нужно написать это так:источник
Я сделал то же самое с SQL Server 2012, и он работал
источник
В зависимости от вашей версии (2012?) SQL Server помимо IF EXISTS вы также можете использовать MERGE следующим образом:
источник
Другой SQL, тот же принцип. Вставлять только в том случае, если предложение в, где не существует, терпит неудачу
источник
Как объяснено в приведенном ниже коде: выполните приведенные ниже запросы и проверьте себя.
Вставить запись:
Теперь попробуйте снова вставить ту же запись:
Вставьте другую запись:
источник
Вы можете использовать
GO
команду. Это возобновит выполнение операторов SQL после ошибки. В моем случае у меня есть несколько 1000 операторов INSERT, где несколько таких записей уже существует в базе данных, я просто не знаю, какие из них. Я обнаружил, что после обработки нескольких сотен выполнение просто останавливается с сообщением об ошибке, которое не может быть,INSERT
поскольку запись уже существует. Довольно раздражает, но выкладыватьGO
решено это. Возможно, это не самое быстрое решение, но скорость не была моей проблемой.источник
GO
такое пакетный разделитель? Это не помогает предотвратить дублирование записей.