SQL-запрос выполняется в стандарте SQL Server 2008, но не на предприятии - PullRequest
0 голосов
/ 18 октября 2011

У меня проблема с запросом, работающим на SQL Server 2008 Enterprise.Запрос представляет собой вставку в таблицу из другого, но он проверяет, что запись вставляется только один раз.Запрос делает что-то вроде этого:

insert into A(...)
--complex select from table B as b
WHERE NOT EXISTS (SELECT 1 FROM A WHERE id = b.id)

Редактировать: этот запрос выполняет следующее: Если «сложный выбор» из B выбирает запись 45 (то есть запись с id = 45) дважды, тогда гдеВ первый раз появляется запись 45, поэтому она вставляется в A. Затем появляется вторая запись 45, условие where ложно, поэтому она не вставляется в A дважды.

Этот запрос работает нормальнов стандартном выпуске SQL Server 2008, так что я думаю, что проблема заключается в разнице между версиями SQL Server (например, набор по умолчанию отличается или что-то в этом духе)проблема.Нет сообщения об ошибке, единственной видимой ошибкой является то, что в стандарте я получаю запись 45 один раз, а на предприятии я получаю ее дважды.Есть идеи?

Ответы [ 2 ]

1 голос
/ 19 октября 2011

Я почти уверен, что поведение, которое вы говорите в Standard Edition, вызвано не какой-то другой причиной, по которой вы думаете.

Похоже, вы ожидаете, что если ваши значения INSERT ed содержат дубликаты, то один из них будет INSERTED, и тогда NOT EXISTS будет иметь значение false из-за существования новой добавленной строки. Однако AFAIK это не так, как это должно работать. Глядя на простой INSERT .. SELECT, как показано ниже.

CREATE TABLE A(id INT PRIMARY KEY)

CREATE TABLE B(id INT PRIMARY KEY)

INSERT INTO A
SELECT *
FROM B

Дает следующий план

Simple Select

Добавление предложения NOT EXISTS

INSERT INTO A
SELECT *
FROM B
WHERE NOT EXISTS (SELECT 1 FROM A WHERE id = B.id)

Изменяет план следующим образом

Sub query

Кроме того, теперь план, включающий в себя анти-полусоединение SQL Server, добавил нетерпеливую катушку в план перед вставкой кластерного индекса в A. Это оператор блокировки, и его цель - убедиться, что весь SELECT вычислен до того, как все строки будут вставлены в B (относится к Halloween Protection ).

Однако вы не обязательно можете видеть катушку в своих планах. например SQL Server может также выбрать использование другого оператора блокировки, такого как SORT или хеш-анти-полусоединение.

Пожалуйста, опубликуйте план выполнения, по крайней мере, для стандартной версии и желательно для обеих. Также запросы, чтобы мы могли видеть, используете ли вы какие-либо недетерминированные конструкции.

0 голосов
/ 18 октября 2011

попробуйте реструктурировать ваш запрос и посмотрите, работает ли он. Вместо NOT EXISTS объедините таблицы в запросе вставки:

INSERT A(...)
SELECT ... FROM B LEFT JOIN A ON B.id = A.id
WHERE B.id = 45 AND A.id IS NULL

, тогда вы выполняете выбор только один раз.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...