Переменная в таблицу, не CTE - PullRequest
2 голосов
/ 11 сентября 2011

Почему это допустимо:

DECLARE @Party TABLE 
(
  PartyID nvarchar(10)
)

INSERT INTO @Party
  SELECT Name FROM
  (INSERT INTO SomeOtherTable
     OUTPUT inserted.Name
          VALUES ('hello')) [H]

SELECT * FROM @Party

Но следующий блок выдает мне ошибку:

WITH Hey (Name) 
AS (
  SELECT Name FROM
  (INSERT INTO SomeOtherTable
    OUTPUT inserted.Name
    VALUES ('hello')) [H]
        )

SELECT * FROM Hey

Второй блок выдает мне ошибку «Вложенный INSERT, UPDATE, DELETEили оператор MERGE недопустим в операторе SELECT, который не является непосредственным источником строк для оператора INSERT.

Кажется, говорят, что вложенные операторы INSERT разрешены, но в моем случае CTE я этого не сделалгнездо внутри другой INSERT. Я удивлен этим ограничением. Есть ли обходные пути в моем случае CTE?

1 Ответ

1 голос
/ 11 сентября 2011

Что касается того, почему это недопустимо, то, допустив, что эти SELECT операции с побочными эффектами вызовут всевозможные проблемы, которые я себе представляю.

CTE не материализуются заранее в свои собственныевременная таблица, что же должно возвращать следующее:

;WITH Hey (Name) 
AS 
(
...
)
SELECT name 
FROM Hey
JOIN some_other_table ON Name = name

Если Оптимизатор запросов решил использовать план с вложенными циклами и Hey в качестве таблицы управления, то предположительно произойдет одна вставка.Однако, если бы он использовал some_other_table в качестве таблицы управления, тогда CTE будет оцениваться столько раз, сколько строк в этой другой таблице, и поэтому произойдет многократное вставление.За исключением случаев, когда Оптимизатор запросов решил добавить катушку в план, и тогда он будет оцениваться только один раз.

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

...