开发者

Output to Table Variable, Not CTE

开发者 https://www.devze.com 2023-04-03 20:48 出处:网络
Why is this legal: DECLARE @Party TABLE ( PartyID nvarchar(10) ) INSERT INTO @Party SELECT Name FROM (INSERT INTO SomeOtherTable

Why is this legal:

DECLARE @Party TABLE 
(
  PartyID nvarchar(10)
)

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

SELECT * FROM @Party

But the next block gives me an error:

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

SELECT * FROM Hey

The second block gives me the error "A nested INSERT, UPDATE, DELETE, or MERGE statement is not allowed in a SELECT statement that is not the immediat开发者_C百科e source of rows for an INSERT statement.

It seems to be saying thst nested INSERT statements are allowed, but in my CTE case I did not nest inside another INSERT. I'm surprised at this restriction. Any work-arounds in my CTE case?


As for why this is illegal, allowing these SELECT operations with side effects would cause all sorts of problems I imagine.

CTEs do not get materialised in advance into their own temporary table so what should the following return?

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

If the Query Optimiser decided to use a nested loops plan and Hey as the driving table then presumably one insert would occur. However if it used some_other_table as the driving table then the CTE would get evaluated as many times as there were rows in that other table and so multiple inserts would occur. Except if the Query Optimiser decided to add a spool to the plan and then it would only get evaluated once.

Presumably avoiding this sort of mess is the motivation for this restriction (as with the restrictions on side effects in functions)

0

精彩评论

暂无评论...
验证码 换一张
取 消