使用带有包含JOIN的CTE的OUTPUT子句,可以在单个语句中使用UPDATE和SELECT吗?

Sir*_*lot 8 t-sql common-table-expression sql-server-2008-r2

我们有许多存储过程,BizTalk使用这些存储过程从队列(和连接表)中获取n行,并同时更新这些项的状态.

我试图修改这些查询以删除表变量的使用,而是在单个语句中完成工作.我已经成功完成了一些,但是这个特殊的例子很棘手,因为joinCTE中有一个,我希望返回一些已连接的列,即使它们不是它们的一部分update.

这就是我想出的:

;with q as
(
    select top (@FetchCount) 
        iq.InQueueId,
        itk.[Message],
        iq.PatNo,
        iq.DistrictNo,
        itk.Interaction,
        iq.[Status]
    from
        InQueue iq
        join Itk on iq.InQueueId = itk.InQueueId
        join [Endpoint] e on iq.[Endpoint] = e.EndpointId
        join EndpointName en on en.EndpointNameId = e.Name
    where
        en.Name = 'XYZ'
        and iq.[Status] = @StatusNew
    order by
        iq.InQueueId
)
update
    q
set
    [Status] = @StatusSelected
output
    inserted.InQueueId as [Id],
    inserted.[Message] as [Msg],
    inserted.DistrictNo,
    inserted.Interaction
Run Code Online (Sandbox Code Playgroud)

这会立即失败并出现以下错误:

不允许列引用"inserted.Message",因为它引用了在此语句中未被修改的基表.

显然,这是因为消息交互列不能作为inserted集合的一部分返回,因为它们位于不同的表中,因此未更新.

所以我试图将output条款改为:

output
    inserted.InQueueId as [Id],
    q.[Message] as [Msg],
    inserted.DistrictNo,
    q.Interaction
Run Code Online (Sandbox Code Playgroud)

这失败并出现错误:

无法绑定多部分标识符"q.Message".

是否可以在不重写查询以使用临时表或表变量的情况下实现此目的?

Cal*_*eth 12

您可以使用deletedoutput子句中的set来引用CTE中未更新的表中的列

例如

output
    inserted.InQueueId as [Id],
    deleted.[Message] as [Msg],
    inserted.DistrictNo,
    deleted.Interaction
Run Code Online (Sandbox Code Playgroud)

deletedinserted集的update也可以看作是之前和之后,虽然这里的术语匹配delete...outputinsert...output

  • 这正是解决我遇到的问题所需要的.我希望我能+10这个答案. (3认同)