输出到表变量,而不是 CTE

发布于 2024-12-03 20:34:38 字数 606 浏览 0 评论 0原文

为什么这是合法的:

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

第二个块给了我错误“在不是行的直接源的 SELECT 语句中不允许嵌套 INSERT、UPDATE、DELETE 或 MERGE 语句INSERT 语句。

似乎是说允许嵌套 INSERT 语句,但在我的 CTE 情况下,我没有嵌套在另一个 INSERT 中,我对我的 CTE 情况有任何解决方法吗?

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 immediate 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?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

迷雾森÷林ヴ 2024-12-10 20:34:39

至于为什么这是非法的,允许这些具有副作用的 SELECT 操作会导致我想象的各种问题。

CTE不会提前具体化到它们自己的临时表中,那么以下应该返回什么?

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

如果查询优化器决定使用嵌套循环计划和 Hey 作为驱动表,那么可能会发生一次插入。但是,如果它使用 some_other_table 作为驱动表,那么 CTE 将被评估与其他表中的行一样多的次数,因此会发生多次插入。除非查询优化器决定将假脱机添加到计划中,然后它只会被评估一次。

想必避免这种混乱是这种限制的动机(就像对函数副作用的限制一样)

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)

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文