简体   繁体   English

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

[英]How to update the source table in the MERGE statement?

I have a table tbBroker on my local database and a table Agency on linked server object "DIS". 我的本地数据库上有一个表tbBroker ,而链接服务器对象“ DIS”上有一个表Agency

I am trying to migrate data from local's tbBroker to DIS's Agency table 我正在尝试将数据从本地的tbBroker迁移到DIS的Agency

Also note that 另请注意

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

Also, tbBroker has two additional columns DISImportFlag bit and DISCreatTS datetime . 另外, tbBroker还有两个附加列DISImportFlag bitDISCreatTS datetime These two fields should be updated to 1 and GETDATE() whenever data is migrated (during insertion) from tbBroker to Agency table in order to determine which rows have been migrated. 每当将数据从tbBroker迁移到Agency表时(插入期间),这两个字段应更新为1GETDATE() ,以确定已迁移的行。

I have written the following query 我写了以下查询

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

When we execute the above query it throws error message 当我们执行上面的查询时,它会引发错误消息

A MERGE statement must be terminated by a semi-colon (;) MERGE语句必须以分号(;)终止

after adding the following line 添加以下行后

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

Edit from comments 根据评论编辑

The source table tbBroker has a primary key column BrokerID . 源表tbBroker具有主键列BrokerID

I want to update in the source table those rows that were inserted into the target table, ie those rows that didn't exist in the target table before MERGE . 我想在源表中更新那些插入到目标表中的行,即在MERGE之前在目标表中不存在的那些行。

I don't think you can change some table other than TARGET using a single MERGE statement. 我认为您无法使用单个MERGE语句更改除TARGET其他表。 But, you can use OUTPUT clause to capture the result of the MERGE in a helper/temporary table and then update your SOURCE based on that. 但是,您可以使用OUTPUT子句在帮助器/临时表中捕获MERGE的结果,然后基于该表更新SOURCE

You said that you want to update only those rows that were inserted into the Target, ie those that didn't exist in the Target before MERGE . 您说过,您只想更新那些插入到Target中的行,即MERGE之前Target中不存在的那些行。

Output IDs of inserted rows into the temporary table and then use it to update the Source table. 插入到临时表中的行的输出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;

Obviously, wrap this whole thing in a transaction and TRY ... CATCH and add appropriate error handling. 显然,将整个内容包装在一个事务中并TRY ... CATCH并添加适当的错误处理。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM