更新CTE更新基础表

时间:2014-06-17 06:49:21

标签: sql-server tsql common-table-expression

数据库平台 - MS SQL Server 2008R2 我有这张桌子 -

CREATE TABLE [dbo].[CaseTest](
    [SampleText] [varchar](5) NULL,
    [ID] [int] NULL,
    [Name] [nchar](10) NULL
)

GO

填充样本数据

INSERT INTO CaseTest
VALUES ('Text1',1,NULL),
('Text2',2,NULL),
('Text3',3,NULL),
('Text4',4,NULL),
('Text5',5,NULL)

现在,当我运行以下查询时,我真的没想到数据有任何变化,但我发现实际的表数据已经更新。

WITH CTE AS(
SELECT * FROM casetest
)
UPDATE CTE SET Name = 'NameText'

这是预期的行为吗?这究竟是如何发生的?

1 个答案:

答案 0 :(得分:3)

你自己在评论中观察到:

  

我认为这将毫无意义

实际上,对于任何实际对数据库进行更改的语句都是如此 - 每个这样的操作都可以作为无操作进行优化。因此,在这种情况下,甚至允许您在创建CTE后编写除SELECT之外的其他内容实际上也没有意义。

但这不是他们选择退出的路线 - 他们确实允许写UPDATEINSERTDELETE等。通过相同的逻辑,它们允许将某些更新操作应用于视图。如果数据库引擎可以使用您的UPDATE语句,并且通过CTE可以将单个目标表确定为UPDATE,则允许通过CTE UPDATE


  

因为CTE只是一个内存中的对象

不是。它只是一个命名查询,在编写CTE时没有任何实现。实际上,CTE被插入到使用它的最终查询中(在引用的地方),然后优化并执行整个查询。

数据库引擎可能在优化最终查询时决定将部分或全部CTE实现到存储中(通过它的假脱机运算符),但这是稍后发生的优化决策 - 还有一个引擎同样能够决定使用它甚至用于简单的非CTE查询。