如何在MERGE语句中更新源表?

Nid*_*ida 3 sql t-sql sql-server sql-server-2008

tbBroker在本地数据库上有一个表,Agency在链接服务器对象“DIS”上有一个表。

我正在尝试将数据从本地迁移tbBroker到 DISAgency

还要注意的是

tbBroker's Columns  =  Agency's Columns
BrokerCode          =  AgencyNumber
BusinesssName       =  AgencyName
City                =  City
tbSystemUser.EmailAddress = EmailAddress
Run Code Online (Sandbox Code Playgroud)

此外,tbBroker还有两个额外的列DISImportFlag bitDISCreatTS datetime. 这两个字段应该被更新为1GETDATE()每当数据从迁移(在插入过程中)tbBrokerAgency表,以确定哪些行已被迁移。

我写了以下查询

       USE [DISTemp];
       MERGE INTO
       [dbo].[Agency] AS [TARGET]
       USING
       [aginbr].[dbo].[tbBroker] AS [SOURCE]
       ON
       [TARGET].[AgencyNumber] COLLATE Latin1_General_CI_AI = [SOURCE].[BrokerCode]
       WHEN NOT MATCHED BY TARGET THEN
       INSERT (    
       [AgencyName]
       , [Address1]
       , [Address2]
       , [PostalCode]
       , [City]
       , [Phone]
       , [EmailAddress]  
       )
       VALUES (
       [SOURCE].[BUSINESSNAME]
       , [SOURCE].[ADDRESS]
       , [SOURCE].[AddressLine2]
       , [SOURCE].[Zip]
       , [SOURCE].[City]
       , [SOURCE].[Phone]
       , [SOURCE].[Email]
       )
       UPDATE SET [SOURCE].[DISImportFlag] = 1,[SOURCE].[DISCreatTS] = GETDATE()
       WHEN MATCHED THEN
       UPDATE SET
       [TARGET].[AgencyName] = [SOURCE].[BUSINESSNAME]
        , [TARGET].[Address1] = [SOURCE].[ADDRESS]
        , [TARGET].[Address2] = [SOURCE].[AddressLine2]
        , [TARGET].[PostalCode] = [SOURCE].[Zip]
        , [TARGET].[City] = [SOURCE].[City]
        , [TARGET].[Phone] = [SOURCE].[Phone]
        , [TARGET].[EmailAddress] = [SOURCE].[Email];
Run Code Online (Sandbox Code Playgroud)

当我们执行上述查询时,它会抛出错误消息

MERGE 语句必须以分号 (;)

添加以下行后

   UPDATE SET [SOURCE].[DISImportFlag] = 1,[SOURCE].[DISCreatTS] = GETDATE()
Run Code Online (Sandbox Code Playgroud)

从评论中编辑

源表tbBroker有一个主键列BrokerID

我想在源表中更新那些插入到目标表中的行,即之前目标表中不存在的那些行MERGE

Vla*_*nov 5

我认为除了TARGET使用单个MERGE语句之外,您无法更改某些表。但是,您可以使用OUTPUT子句MERGE在帮助程序/临时表中捕获结果,然后SOURCE根据该结果更新您的结果。

你说你只想更新那些插入到目标中的行,即那些之前不存在于目标中的行MERGE

IDs将插入的行输出到临时表中,然后使用它来更新Source表。

CREATE TABLE #Temp(
    BrokerID int NOT NULL,
CONSTRAINT [PK_Broker] PRIMARY KEY CLUSTERED
(
    BrokerID ASC
));

INSERT INTO #Temp (BrokerID)
SELECT TableChanges.BrokerID
FROM
    (
        MERGE INTO [dbo].[Agency] AS [TARGET]
        USING [aginbr].[dbo].[tbBroker] AS [SOURCE]
        ON [TARGET].[AgencyNumber] COLLATE Latin1_General_CI_AI = [SOURCE].[BrokerCode]
        WHEN NOT MATCHED BY TARGET THEN
        INSERT
        (
            [AgencyName]
            , [Address1]
            , [Address2]
            , [PostalCode]
            , [City]
            , [Phone]
            , [EmailAddress]
        )
        VALUES
        (
            [SOURCE].[BUSINESSNAME]
            , [SOURCE].[ADDRESS]
            , [SOURCE].[AddressLine2]
            , [SOURCE].[Zip]
            , [SOURCE].[City]
            , [SOURCE].[Phone]
            , [SOURCE].[Email]
        )
        WHEN MATCHED THEN
        UPDATE SET
            [TARGET].[AgencyName] = [SOURCE].[BUSINESSNAME]
            , [TARGET].[Address1] = [SOURCE].[ADDRESS]
            , [TARGET].[Address2] = [SOURCE].[AddressLine2]
            , [TARGET].[PostalCode] = [SOURCE].[Zip]
            , [TARGET].[City] = [SOURCE].[City]
            , [TARGET].[Phone] = [SOURCE].[Phone]
            , [TARGET].[EmailAddress] = [SOURCE].[Email]
        OUTPUT $action, [SOURCE].BrokerID
    ) AS TableChanges (MergeAction, BrokerID)
WHERE TableChanges.MergeAction = 'INSERT'
;

UPDATE [aginbr].[dbo].[tbBroker]
SET
    [DISImportFlag] = 1
    ,[DISCreatTS] = GETDATE()
WHERE
    BrokerID IN 
    (
        SELECT T.BrokerID FROM #Temp AS T
    )
;

DROP TABLE #Temp;
Run Code Online (Sandbox Code Playgroud)

显然,将整个事情包装在一个事务中TRY ... CATCH并添加适当的错误处理。