SQL Merge实现数据同步
实例如下:
USE [LVDU_MDM] GO /****** Object: StoredProcedure [dbo].[SyncRole] Script Date: 2018/7/6 13:59:16 ******/ SET ANSI_NULLS ON GO SET QUOTED_IDENTIFIER ON GO -- ============================================= -- Author: Adolph.Chen -- Create date: 2018-07-06 -- Description: 从BPM同步角色和人员角色关系信息 -- SELECT * FROM [dbo].[Log_ServiceLog] WHERE ServiceCode='SyncRole' ORDER BY InvokeTime DESC -- EXEC [dbo].[SyncRole] 1,1 -- ============================================= AlTER PROCEDURE [dbo].[SyncRole] @SyncRole INT--同步角色:1代表同步,0代表不同步 ,@SyncUserRole INT--同步人员角色关系:1代表同步,0代表不同步 AS BEGIN BEGIN TRY IF(@SyncRole=1) BEGIN PRINT '同步角色START' INSERT INTO [dbo].[Log_ServiceLog](ServiceLogID,AppID,ServiceCode,InvokeTime,Result,ExceptionMsg) VALUES(NEWID(),1,'SyncRole',GETDATE(),1,'同步角色START'); --获取数据 SELECT * INTO #Temp_Role FROM [LVDU_BPM].[dbo].[V_Guest_GetUserRoleStatus] SELECT '' AS RoleType ,o.OrganizationCode+'-'+o.RoleCode AS RoleCode ,o.OrganizationName+'-'+o.RoleName AS RoleName ,NULL AS Description ,1 AS Status ,NULL AS CreateUserID ,GETDATE() AS CreateDate ,NULL AS ModifyUserID ,NULL AS ModifyDate INTO #Temp_RoleInfo FROM #Temp_Role o group by o.OrganizationCode,o.RoleCode,o.OrganizationName,o.RoleName --导入数据 MERGE INTO [dbo].[SYS_Role] AS T USING #Temp_RoleInfo AS S ON T.RoleCode=S.RoleCode WHEN MATCHED--源数据、目标数据同时存在,更新 THEN UPDATE SET T.RoleName=S.RoleName WHEN NOT MATCHED--目标数据不存在,插入 THEN INSERT VALUES( S.RoleType ,S.RoleCode ,S.RoleName ,S.Description ,S.Status ,S.CreateUserID ,S.CreateDate ,S.ModifyUserID ,S.ModifyDate ) WHEN NOT MATCHED BY SOURCE AND T.RoleID<>1 --源数据不存在,删除 THEN UPDATE SET T.Status=0; DROP TABLE #Temp_RoleInfo DROP TABLE #Temp_Role PRINT '同步角色END' INSERT INTO [dbo].[Log_ServiceLog](ServiceLogID,AppID,ServiceCode,InvokeTime,Result,ExceptionMsg) VALUES(NEWID(),1,'SyncRole',GETDATE(),1,'同步角色END'); END IF(@SyncUserRole=1) BEGIN PRINT '同步人员角色关系START' INSERT INTO [dbo].[Log_ServiceLog](ServiceLogID,AppID,ServiceCode,InvokeTime,Result,ExceptionMsg) VALUES(NEWID(),1,'SyncRole',GETDATE(),1,'同步人员角色关系START'); --获取数据 SELECT *,OrganizationCode+'-'+RoleCode AS Code INTO #Temp_UserRole FROM [LVDU_BPM].[dbo].[V_Guest_GetUserRoleStatus] SELECT u.UserID AS UserID ,r.RoleID AS RoleID INTO #Temp_UserRoleInfo FROM #Temp_UserRole o inner JOIN [dbo].[MDM_User] u on u.UserLoginID = o.UserAccount inner JOIN [dbo].[SYS_Role] r on r.RoleCode = o.Code --导入数据 MERGE INTO [dbo].[SYS_UserRole] AS T USING #Temp_UserRoleInfo AS S ON T.UserID=S.UserID AND T.RoleID=S.RoleID WHEN NOT MATCHED--目标数据不存在,插入 THEN INSERT VALUES( S.UserID ,S.RoleID ) WHEN NOT MATCHED BY SOURCE AND T.RoleID<>1--源数据不存在,删除 THEN DELETE; DROP TABLE #Temp_UserRoleInfo DROP TABLE #Temp_UserRole PRINT '同步人员角色关系END' INSERT INTO [dbo].[Log_ServiceLog](ServiceLogID,AppID,ServiceCode,InvokeTime,Result,ExceptionMsg) VALUES(NEWID(),1,'SyncRole',GETDATE(),1,'同步人员角色关系END'); END END TRY BEGIN CATCH -- 捕获异常 PRINT ERROR_MESSAGE() INSERT INTO [dbo].[Log_ServiceLog](ServiceLogID,AppID,ServiceCode,InvokeTime,Result,ExceptionMsg) VALUES(NEWID(),1,'SyncRole',GETDATE(),1,ERROR_MESSAGE()); END CATCH END
一点小心得:
当你只需要更新目标表部分数据的时候,在MERGE INTO [A] USING [B] ON 后面加where条件是木有用处的
需要在WHEN MATCHED等这种后面加AND条件来过滤数据源中不想被操作到的数据