SQL Server 2012 OUTPUT 子句中的错误

Stu*_*ner 4 sql-server sql-server-2012

给定以下针对 AdventureWorks 数据库的 SQL 代码:

begin transaction;

drop trigger Sales.iduSalesOrderDetail;
alter table Sales.SalesOrderDetail
    add LineNumber int null;
go

with sod as (
    select
        SalesOrderID, 
            /* other cols */
        LineNumber,
        NewLineNumber = row_number() over 
            (partition by SalesOrderID order by SalesOrderDetailID) + 1
    from Sales.SalesOrderDetail
    where SalesOrderID <= 44000)
update sod
set LineNumber = NewLineNumber,
    ModifiedDate = getdate()
output
    inserted.SalesOrderID, 
    /* other cols */
    inserted.LineNumber;

select
    SalesOrderID, 
    /* other cols */
    LineNumber
from Sales.SalesOrderDetail
where SalesOrderID <= 44000;

rollback transaction;
Run Code Online (Sandbox Code Playgroud)

在 SQL Server 2008R2 上运行此代码时,它运行良好;也就是说,它更新输入的数据Sales.SalesOrderDetail并输出结果,该结果与来自以下 SELECT 语句的数据相匹配。

但是,在 SQL Server 2012 上运行此代码时,我收到消息:

消息 4196,级别 16,状态 1,第 2 行
无法在 OUTPUT 子句中引用列“deleted.NewLineNumber”,因为列定义包含使用窗口函数的表达式。

这很奇怪,因为我没有以任何方式引用 delete.NewLineNumber。我尝试删除各种 OUTPUT 列并获得相同的结果。我发现停止错误的唯一两种方法是

  • 使 NewLineNumber 列恰好是row_number()(也就是说:) 的结果NewLineNumber = row_number() over (...);或者
  • 完全删除 OUTPUT 子句。

这可能是 SQL Server 如何处理 CTE 中的表达式的错误吗?有没有其他人遇到过这个问题?

我正在研究可能的解决方法,但我对此很好奇。

Aar*_*and 8

这是 SQL Server 2012 中的错误,将在 SP2 中修复:

http://connect.microsoft.com/SQLServer/feedback/details/779077/output-clause-fails-when-doing-update-using-cte

解决方法是+ 1ROW_NUMBER()计算中删除;这个虚假的错误信息消失了。重写这部分:

  NewLineNumber = row_number() over 
    (partition by SalesOrderID order by SalesOrderDetailID)
    ---------------- remove the +1 here --------------------^^^
  from Sales.SalesOrderDetail
  where SalesOrderID <= 44000)
update sod 
  set LineNumber = NewLineNumber + 1,
  ------- and put it here -------^^^
Run Code Online (Sandbox Code Playgroud)