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

时间:2016-02-18 07:10:22

标签: sql sql-server sql-server-2008 tsql

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

我正在尝试将数据从本地的tbBroker迁移到DIS的Agency

另请注意

tbBroker's Columns  =  Agency's Columns
BrokerCode          =  AgencyNumber
BusinesssName       =  AgencyName
City                =  City
tbSystemUser.EmailAddress = EmailAddress

此外,tbBroker还有两列DISImportFlag bitDISCreatTS datetime。每当从1GETDATE()表迁移数据(插入期间)时,这两个字段都应更新为tbBrokerAgency,以确定哪些行已迁移。< / p>

我写了以下查询

       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];

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

  

MERGE语句必须以分号(;)

结束

添加以下行

   UPDATE SET [SOURCE].[DISImportFlag] = 1,[SOURCE].[DISCreatTS] = GETDATE()

根据评论进行修改

源表tbBroker有一个主键列BrokerID

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

1 个答案:

答案 0 :(得分:4)

我认为您不能使用单个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;

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