数据库平台 - 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'
这是预期的行为吗?这究竟是如何发生的?
答案 0 :(得分:3)
你自己在评论中观察到:
我认为这将毫无意义
实际上,对于任何实际对数据库进行更改的语句都是如此 - 每个这样的操作都可以作为无操作进行优化。因此,在这种情况下,甚至允许您在创建CTE后编写除SELECT
之外的其他内容实际上也没有意义。
但这不是他们选择退出的路线 - 他们确实允许写UPDATE
,INSERT
,DELETE
等。通过相同的逻辑,它们允许将某些更新操作应用于视图。如果数据库引擎可以使用您的UPDATE
语句,并且通过CTE可以将单个目标表确定为UPDATE
,则允许通过CTE UPDATE
。
因为CTE只是一个内存中的对象
不是。它只是一个命名查询,在编写CTE时没有任何实现。实际上,CTE被插入到使用它的最终查询中(在引用的地方),然后优化并执行整个查询。
数据库引擎可能在优化最终查询时决定将部分或全部CTE实现到存储中(通过它的假脱机运算符),但这是稍后发生的优化决策 - 还有一个引擎同样能够决定使用它甚至用于简单的非CTE查询。