【问题标题】:Insert Or Update After a Merge合并后插入或更新
【发布时间】:2013-05-14 12:47:32
【问题描述】:

我在 MS SQL Server 上有以下 MERGE 操作。

DECLARE @data as xml
DECLARE @id as int
DECLARE @version as rowversion
SET @data = ?
SET @id = ?
<# if ( tw.local.enableOptimisticLocking == true ) { #>
SET @version = CAST(? as rowversion)
<# } #>
MERGE [<#=tw.local.dbSchema#>].[<#=tw.local.tableName#>] AS target
USING (Select @id as id, @version version ) as source ON target.id = source.id
WHEN MATCHED <# if ( tw.local.enableOptimisticLocking == true ) { #> AND target.version = source.version <# } #> THEN
    UPDATE SET data = @data
WHEN NOT MATCHED THEN
    INSERT (data) VALUES (@data)
OUTPUT $action as _action<# if ( tw.local.enableOptimisticLocking == true ) { #>, CAST( inserted.version as BigInt) as [version]<# } #>, inserted.id;

我希望对另一个数据库和表有一个 INSERT / UPDATE 语句,以根据上述 MERGE 的结果更新一些列。

我不确定我是否可以在 MERGE 中进行其他 INSERT/UPDATE,或者我是否需要使用 Output 来获取我想要从 MERGE 中插入/更新的所有数据?

我尝试了以下方法,但它不起作用....

DECLARE @data as xml
DECLARE @id as int
DECLARE @version as rowversion
SET @data = ?
SET @id = ?
<# if ( tw.local.enableOptimisticLocking == true ) { #>
SET @version = CAST(? as rowversion)
<# } #>
MERGE [<#=tw.local.dbSchema#>].[<#=tw.local.tableName#>] AS target
USING (Select @id as id, @version version ) as source ON target.id = source.id
WHEN MATCHED <# if ( tw.local.enableOptimisticLocking == true ) { #> AND target.version = source.version <# } #> THEN
    UPDATE SET data = @data
WHEN NOT MATCHED THEN
    INSERT (data) VALUES (@data)
OUTPUT $action as _action<# if ( tw.local.enableOptimisticLocking == true ) { #>, CAST( inserted.version as BigInt) as [version]<# } #>, inserted.id, inserted.version, inserted.data;

IF EXISTS (SELECT INSERTED.* FROM INSERTED LEFT JOIN DELETED ON INSERTED.ID = DELETED.id WHERE DELETED.ID IS NULL)
    BEGIN
        INSERT INTO [EMEAworkflowBPM].[cmf].[BusinessContextReporting] (id, version, data, updatedOn, toProcess)
        SELECT i.id, i.version, i.data, GETDATE(), 1
        FROM Inserted i
        LEFT JOIN [EMEAworkflowBPM].[cmf].[BusinessContextReporting] bcr
        ON i.id = bcr.id AND i.version = bcr.version
        WHERE bcr.id IS NULL;
    END
ELSE IF EXISTS (SELECT INSERTED.* FROM INSERTED INNER JOIN DELETED ON INSERTED.ID = DELETED.ID)
    BEGIN
        UPDATE [EMEAworkflowBPM].[cmf].[BusinessContextReporting]
        SET version = i.version, data = i.data, updatedOn = GETDATE(), toProcess = 1
            FROM Inserted AS i
            LEFT JOIN [EMEAworkflowBPM].[cmf].[BusinessContextReporting] AS bcr
            ON i.id = bcr.id;
    END

非常感谢您的宝贵时间和帮助。

【问题讨论】:

    标签: sql sql-server-2008


    【解决方案1】:

    您必须将 OUTPUT 与 INTO 子句结合起来,并将 UPDATE 和 INSERT 作为 MERGE 之后的新语句。

    看看这个问题中接受的答案:

    Using merge..output to get mapping between source.id and target.id

    【讨论】:

    • 嗨 Olle,您给我的链接似乎使用 2 个临时表将输出结果(即合并后)存储到“临时”表中,然后从这些表中执行他的附加选择逻辑。我可以使用输出来填充我想要的任何表,并在我没有原始数据但进行函数调用的地方添加其他列(即 GETDATE())吗?
    • 你也可以根据 MERGE 是执行 INSERT 还是 UPDATE 来修改 OUTPUT 吗?
    • 您可以使用 $action 查看输出来自哪个操作。像 OUTPUT $action,deleted.*,inserted.*
    • 我认为您应该可以将输出插入真实表格。
    • 我不确定函数调用。你必须尝试一下! :)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-11-28
    • 2012-07-29
    • 2013-09-22
    • 2011-06-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多