SQL Server 2012:无法使用MERGE语句

时间:2016-03-18 15:05:56

标签: sql sql-server sql-server-2012

我有两个数据库TestDB_SourceTestDB_Dest

TestDB_Source数据库中有一些表和数据。

TestDB_Dest包含TestDB_Source数据库中存在的所有表,但没有任何数据。

两个数据库中都有一个表Addresses

在这里,我尝试将表Addresses的数据从TestDB_Source数据库复制到TestDB_Dest数据库。

我正在使用此SQL查询:

BEGIN TRANSACTION SYNC_ADDRESSDATA_TO_DEST
BEGIN TRY
    ----Target Table ----  TestDB_Source.dbo.Addresses  
    ----Source table ----- TestDB_Dest.dbo.Addresses
    MERGE [TestDB_Source].[dbo].[Addresses] AS TARGET
    USING (SELECT [ID], [City], [Country], [State], [ZipCode] 
           FROM [TestDB_Dest].[dbo].[Addresses]) AS SOURCE ON (TARGET.[ID] = SOURCE.[ID]) 

      WHEN MATCHED THEN 
         UPDATE SET TARGET.City = SOURCE.[City],
                    TARGET.State = SOURCE.[State], 
                    TARGET.Country = SOURCE.[Country],
                    TARGET.ZipCode = SOURCE.[ZipCode]

      --When no records are matched, insert the incoming records from source table to target table
      WHEN NOT MATCHED BY TARGET THEN  
         INSERT ([ID], [City], [Country], [State], [ZipCode]) 
         VALUES (SOURCE.[ID], SOURCE.[City], SOURCE.[Country], SOURCE.[State], SOURCE.[ZipCode]);

         SELECT @@ROWCOUNT;
END TRY
BEGIN CATCH
    ROLLBACK TRANSACTION SYNC_ADDRESSDATA_TO_DEST
    RETURN
END CATCH

COMMIT TRANSACTION SYNC_ADDRESSDATA_TO_DEST

由于[TestDB_Dest].[dbo].[Addresses]为空,因此根据未匹配的条件数据应从TestDB_Source复制到TestDB_Dest

但是这里没有插入[TestDB_Dest].[dbo].[Addresses]

的行

有人可以帮我解决这个问题吗?

1 个答案:

答案 0 :(得分:1)

显然我们已经找到了你的问题。您的目标表具有标识列,如果要显式插入该字段,则需要使用IDENTITY_INSERT

您的查询无提示失败,因为您已将其包装在事务中并且在CATCH阻止您只是默默地回滚事务并且不会抛出任何错误消息,这就是您认为插入的原因没发生。

一个简单的例子:

-- This query will execute even though it's erroneous and won't bring anything back
BEGIN
    BEGIN TRY
        SELECT 1/0;
    END TRY
    BEGIN CATCH
    END CATCH
END

-- This query will throw error message, because you can't divide anything by zero. THROW keyword does the job
BEGIN
    BEGIN TRY
        SELECT 1/0;
    END TRY
    BEGIN CATCH
        THROW;
    END CATCH
END

此查询应该有效:

BEGIN TRY
    BEGIN TRANSACTION SYNC_ADDRESSDATA_TO_DEST

    SET IDENTITY_INSERT [TestDB_Dest].[dbo].[Addresses] ON;

    ----Target Table ----  TestDB_Source.dbo.Addresses
    ----Source table ----- TestDB_Dest.dbo.Addresses
    MERGE [TestDB_Dest].[dbo].[Addresses] AS TARGET
    USING (
        SELECT [ID], [City], [Country], [State], [ZipCode]
        FROM [TestDB_Source].[dbo].[Addresses]
        ) AS SOURCE
        ON (TARGET.[ID] = SOURCE.[ID])
    WHEN MATCHED THEN UPDATE
    SET TARGET.City = SOURCE.[City]
        , TARGET.STATE = SOURCE.[State]
        , TARGET.Country = SOURCE.[Country]
        , TARGET.ZipCode = SOURCE.[ZipCode]
    --When no records are matched, insert the incoming records from source table to target table
    WHEN NOT MATCHED BY TARGET THEN INSERT ([ID], [City], [Country], [State], [ZipCode])
            VALUES (SOURCE.[ID], SOURCE.[City], SOURCE.[Country], SOURCE.[State], SOURCE.[ZipCode]);
    SET IDENTITY_INSERT [TestDB_Dest].[dbo].[Addresses] OFF;

    SELECT @@ROWCOUNT;

    COMMIT TRANSACTION SYNC_ADDRESSDATA_TO_DEST
END TRY
BEGIN CATCH
    ROLLBACK TRANSACTION SYNC_ADDRESSDATA_TO_DEST
    THROW;
END CATCH

最重要的是,我认为您使用SOURCETARGET打了个拼写错误。如果您要将数据从[TestDB_Source]复制到[TestDB_Dest],那么[TestDB_Dest]必须是您的目标。

我还修改了您使用交易的方式。这是在TRANSACTION阻止中使用TRY..CATCH的推荐方式。