Cha*_*ace 7 sql-server window-functions output-clause
该条款中是否存在未记录的限制OUTPUT
,或者这是一个错误?
给出下表:
CREATE TABLE t1 (SomeId int, flag bit, value int);
Run Code Online (Sandbox Code Playgroud)
我想在UPDATE
语句中使用计算值,然后使用OUTPUT
输出该值。请注意,计算值未在该部件中使用SET
,这可能允许通过输出左侧列来解决问题。
以下工作正常,它是一个完美标准的可更新子查询(派生表)。
UPDATE subT1
SET flag = 1
OUTPUT inserted.SomeValue
FROM (
SELECT *,
SomeValue = t1.value + 123
FROM t1
) subT1;
Run Code Online (Sandbox Code Playgroud)
然而使用窗口函数会出现一个奇怪的错误:
UPDATE subT1
SET flag = 1
OUTPUT inserted.Sum
FROM (
SELECT *,
Sum = SUM(t1.value) OVER (PARTITION BY t1.SomeId)
FROM t1
) subT1;
Run Code Online (Sandbox Code Playgroud)
Msg 404 Level 16 State 1 Line 3
The column reference "inserted.Sum" is not allowed because it refers to a base table that is not being modified in this statement.
Run Code Online (Sandbox Code Playgroud)
这是没有意义的,因为我们已经确定可以使用 来引用计算列inserted
。
好吧,让我们尝试使用OUTPUT subT1.Sum
无论如何,而不是inserted.Sum
:
Msg 4104 Level 16 State 1 Line 3
The multi-part identifier "subT1.Sum" could not be bound.
Run Code Online (Sandbox Code Playgroud)
这是有道理的,因为该表引用已被修改,并且文档说:
如果正在修改的表也在 FROM 子句中指定,则对该表中的列的任何引用都必须使用 INSERTED 或 DELETED 前缀进行限定。
同时,如果我在第二个表上使用联接:
CREATE TABLE t2 (SomeId int, flag bit, value int);
Run Code Online (Sandbox Code Playgroud)
效果很好
UPDATE t1
SET flag = 1
OUTPUT subT2.Sum
FROM t1
JOIN (
SELECT t2.*,
Sum = SUM(t2.value) OVER (PARTITION BY t2.SomeId)
FROM t2
) subT2 ON subT2.SomeId = t1.SomeId;
Run Code Online (Sandbox Code Playgroud)
那么,窗口函数引发该错误的事实究竟是一个错误,还是一个未记录的限制?
话虽如此,子查询内的联接也是不允许的,因此很可能这是一个未记录的限制。
UPDATE subT1
SET flag = 1
OUTPUT inserted.Sum
FROM (
SELECT t1.*,
Sum = t2.value
FROM t1
JOIN t2 ON t2.SomeId = t1.SomeId
) subT1;
Run Code Online (Sandbox Code Playgroud)
Msg 404 Level 16 State 1 Line 3
The column reference "inserted.Sum" is not allowed because it refers to a base table that is not being modified in this statement.
Run Code Online (Sandbox Code Playgroud)
我没有看到文档中明确涵盖这一点,但OUTPUT deleted.Sum
确实有效。
这确实有一定意义,因为它SUM
是根据“更新前”而不是“更新后”的值计算的
即下面返回 a SUM
of2
而不是0
CREATE TABLE t1 (SomeId int, flag bit, value int);
INSERT T1 values (1,1,1), (1,1,1);
UPDATE subT1
SET flag = 1, value = 0
OUTPUT deleted.Sum AS [SUM(value)],
deleted.value AS [deleted.value],
inserted.value AS [inserted.value]
FROM (
SELECT *,
Sum = SUM(t1.value) OVER (PARTITION BY t1.SomeId)
FROM t1
) subT1;
DROP TABLE t1
Run Code Online (Sandbox Code Playgroud)
总和(值) | 删除的值 | 插入值 |
---|---|---|
2 | 1 | 0 |
2 | 1 | 0 |
对于更简单的表达式,SomeValue = t1.value + 123
它能够通过在输出流上添加计算标量inserted.SomeValue
来计算不同deleted.SomeValue
,但可能窗口函数也太复杂而无法做到这一点。
即下面的...
CREATE TABLE t1 (SomeId int, flag bit, value int);
INSERT T1 values (1,1,1), (1,1,1);
UPDATE subT1
SET flag = 1,
value = 999
OUTPUT deleted.SomeValue AS [deleted.SomeValue],
inserted.SomeValue AS [inserted.SomeValue]
FROM (
SELECT *,
SomeValue = t1.value + 123
FROM t1
) subT1;
DROP TABLE t1
Run Code Online (Sandbox Code Playgroud)
退货
已删除.SomeValue | 插入的.SomeValue |
---|---|
124 | 1122 |
124 | 1122 |
并且执行计划是一样的
UPDATE t1
SET flag = 1,
value = 999
OUTPUT deleted.value + 123 AS [deleted.SomeValue],
inserted.value + 123 AS [inserted.SomeValue]
FROM t1;
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
286 次 |
最近记录: |