【问题标题】:It is possible to UPDATE and SELECT in single statement using OUTPUT clause with CTE containing JOIN?是否可以在单个语句中使用 OUTPUT 子句和包含 JOIN 的 CTE 进行 UPDATE 和 SELECT?
【发布时间】:2013-07-23 12:01:00
【问题描述】:

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

我正在尝试修改这些查询以删除表变量的使用,而是在单个语句中完成工作。我已经成功了一些,但是这个特定的例子很棘手,因为 CTE 中有一个 join,我想返回一些连接的列,即使它们不是 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

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

列引用“inserted.Message”是不允许的,因为它 指的是在这个语句中没有被修改的基表。

很明显,这是因为列 MessageInteraction 不能作为 inserted 集合的一部分返回,因为它们位于不同的表中,因此不是更新了。

所以我尝试将output 子句更改为:

output
    inserted.InQueueId as [Id],
    q.[Message] as [Msg],
    inserted.DistrictNo,
    q.Interaction

这失败并出现错误:

无法绑定多部分标识符“q.Message”。

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

【问题讨论】:

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


    【解决方案1】:

    您可以使用输出子句中设置的deleted 来引用未更新表中 CTE 中的列

    例如

    output
        inserted.InQueueId as [Id],
        deleted.[Message] as [Msg],
        inserted.DistrictNo,
        deleted.Interaction
    

    update 中的 deletedinserted 集合也可以被认为是前后,尽管这里的术语与 delete...outputinsert...output 匹配

    【讨论】:

    • 谢谢,那是我没有尝试过的一件事!我认为他们真的可以改进这里的关键字选择;在 deleted 集中查找未更改的值似乎不合逻辑。
    • 这正是我解决遇到的问题所需要的。我希望我能 +10 这个答案。
    猜你喜欢
    • 2015-11-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-09-05
    • 1970-01-01
    • 1970-01-01
    • 2011-08-29
    • 1970-01-01
    相关资源
    最近更新 更多