LOGO OA教程 ERP教程 模切知识交流 PMS教程 CRM教程 开发文档 其他文档  
 
网站管理员

MSSQL跨数据库访问:从远程服务器同步人员数据

admin
2026年4月15日 14:59 本文热度 48

今天我们来学习如何在SQL Server中跨数据库访问数据,实现不同服务器之间的数据同步。

一、跨数据库访问的三种方式

方式
适用场景
配置复杂度
性能
OPENDATASOURCE
临时访问
简单
一般
链接服务器
频繁访问
中等
较好
OPENQUERY
通过链接服务器
中等
较好

二、方案

方案一:使用OPENDATASOURCE(临时访问)

CREATE PROCEDURE usp_SyncPersonnelDataASBEGIN    SET NOCOUNT ON
    BEGIN TRY        BEGIN TRANSACTION
        -- 1. 创建临时表存放远程数据        SELECT             CAST(工号 AS INTAS PersonNo,            姓名 AS PersonName,            直间接 AS DutyType        INTO #TempPersonnel        FROM OPENDATASOURCE(            'SQLOLEDB',            'DATA SOURCE=DATABAK;UID=sa;PWD=密码;'        ).gwidb.dbo.out_TANXUEMEISYSTEMpawf
        -- 2. 处理离职人员(更新状态为离职)        UPDATE dp        SET Workflag = 'N'        FROM syteline.SHATDB.dbo.DeptPerson dp        LEFT JOIN #TempPersonnel tp ON dp.PersonNo = tp.PersonNo        WHERE tp.PersonNo IS NULL  -- 在远程表中不存在 = 已离职            AND dp.Workflag = 'Y'  -- 只处理在职的
        -- 3. 处理在职人员(存在则更新,不存在则新增)        -- 3.1 更新已存在人员        UPDATE dp        SET             PersonNo = tp.PersonNo,            [Name] = tp.PersonName,            Duty = tp.DutyType,            Workflag = 'Y'        FROM syteline.SHATDB.dbo.DeptPerson dp        INNER JOIN #TempPersonnel tp ON dp.PersonNo = tp.PersonNo
        -- 3.2 新增不存在人员        INSERT INTO syteline.SHATDB.dbo.DeptPerson (            PersonNo,             [Name],             Workflag,             Duty        )        SELECT             tp.PersonNo,            tp.PersonName,            'Y',            tp.DutyType        FROM #TempPersonnel tp        WHERE NOT EXISTS (            SELECT 1 FROM syteline.SHATDB.dbo.DeptPerson dp             WHERE dp.PersonNo = tp.PersonNo        )
        -- 清理临时表        DROP TABLE #TempPersonnel
        COMMIT TRANSACTION        PRINT '人员数据同步完成'
    END TRY    BEGIN CATCH        ROLLBACK TRANSACTION        DECLARE @ErrorMessage NVARCHAR(4000= ERROR_MESSAGE()        DECLARE @ErrorSeverity INT = ERROR_SEVERITY()        RAISERROR(@ErrorMessage@ErrorSeverity1)    END CATCHEND

方案二:使用链接服务器(推荐)

-- 1. 首先创建链接服务器(只需执行一次)EXEC sp_addlinkedserver     @server = 'RemoteHR',  -- 链接服务器名称    @srvproduct = '',    @provider = 'SQLOLEDB',    @datasrc = 'DATABAK'   -- 远程服务器地址
EXEC sp_addlinkedsrvlogin     @rmtsrvname = 'RemoteHR',    @useself = 'false',    @rmtuser = 'sa',    @rmtpassword = '密码'
-- 2. 使用链接服务器同步数据CREATE PROCEDURE usp_SyncPersonnelData_LinkedServerASBEGIN    SET NOCOUNT ON
    BEGIN TRY        BEGIN TRANSACTION
        -- 获取远程数据        SELECT             CAST(工号 AS INTAS PersonNo,            姓名 AS PersonName,            直间接 AS DutyType        INTO #TempPersonnel        FROM [RemoteHR].gwidb.dbo.out_TANXUEMEISYSTEMpawf
        -- 批量更新操作(同上)        -- ... (更新和插入代码与方案一相同)
        DROP TABLE #TempPersonnel        COMMIT TRANSACTION
    END TRY    BEGIN CATCH        ROLLBACK TRANSACTION        THROW    END CATCHEND

方案三:使用OPENQUERY(更灵活)

CREATE PROCEDURE usp_SyncPersonnelData_OpenQueryASBEGIN    SET NOCOUNT ON
    -- 使用OPENQUERY执行复杂的远程查询    SELECT *    INTO #TempPersonnel    FROM OPENQUERY(RemoteHR, '        SELECT             CAST(工号 AS INT) AS PersonNo,            姓名 AS PersonName,            直间接 AS DutyType        FROM gwidb.dbo.out_TANXUEMEISYSTEMpawf        WHERE 直间接 IN (''直'', ''间接'')  -- 可以在远程过滤数据    ')
    -- 后续处理同上...END

三、性能对比测试

-- 创建测试存储过程,对比三种方式性能CREATE PROCEDURE usp_TestSyncPerformanceASBEGIN    DECLARE @StartTime DATETIME, @EndTime DATETIME
    -- 测试OPENDATASOURCE    SET @StartTime = GETDATE()    EXEC usp_SyncPersonnelData    SET @EndTime = GETDATE()    PRINT 'OPENDATASOURCE耗时:' + CAST(DATEDIFF(ms, @StartTime@EndTimeAS VARCHAR+ 'ms'
    -- 测试链接服务器    SET @StartTime = GETDATE()    EXEC usp_SyncPersonnelData_LinkedServer    SET @EndTime = GETDATE()    PRINT '链接服务器耗时:' + CAST(DATEDIFF(ms, @StartTime@EndTimeAS VARCHAR+ 'ms'
    -- 测试OPENQUERY    SET @StartTime = GETDATE()    EXEC usp_SyncPersonnelData_OpenQuery    SET @EndTime = GETDATE()    PRINT 'OPENQUERY耗时:' + CAST(DATEDIFF(ms, @StartTime@EndTimeAS VARCHAR+ 'ms'END

四、完整解决方案:带参数和日志

-- 创建同步日志表CREATE TABLE SyncLog (    LogID INT IDENTITY PRIMARY KEY,    SyncTime DATETIME DEFAULT GETDATE(),    SyncType NVARCHAR(50),    RecordsAffected INT,    Status NVARCHAR(20),    ErrorMessage NVARCHAR(MAX))
-- 最终版同步存储过程CREATE PROCEDURE usp_SyncHRData    @SyncType NVARCHAR(20= 'ALL',  -- ALL, PERSONNEL, DEPT    @DebugMode BIT = 0                 -- 1:只显示不执行ASBEGIN    SET NOCOUNT ON
    DECLARE @StartTime DATETIME = GETDATE()    DECLARE @RecordsAffected INT = 0    DECLARE @Status NVARCHAR(20= 'SUCCESS'    DECLARE @ErrorMessage NVARCHAR(MAX) = ''
    BEGIN TRY        -- 检查链接服务器是否可用        IF NOT EXISTS (SELECT 1 FROM sys.servers WHERE name = 'RemoteHR')        BEGIN            RAISERROR('链接服务器RemoteHR不存在,请先创建'161)            RETURN        END
        BEGIN TRANSACTION
        -- 1. 获取远程数据        SELECT             CAST(工号 AS INTAS PersonNo,            姓名 AS PersonName,            直间接 AS DutyType        INTO #TempData        FROM OPENQUERY(RemoteHR, '            SELECT 工号, 姓名, 直间接             FROM gwidb.dbo.out_TANXUEMEISYSTEMpawf            WHERE 工号 IS NOT NULL        ')
        IF @DebugMode = 1        BEGIN            SELECT * FROM #TempData            ROLLBACK TRANSACTION            RETURN        END
        -- 2. 根据类型同步数据        IF @SyncType IN ('ALL''PERSONNEL')        BEGIN            -- 更新离职人员            UPDATE dp            SET Workflag = 'N',                LastUpdate = GETDATE()            FROM syteline.SHATDB.dbo.DeptPerson dp            LEFT JOIN #TempData td ON dp.PersonNo = td.PersonNo            WHERE td.PersonNo IS NULL                 AND dp.Workflag = 'Y'
            SET @RecordsAffected = @RecordsAffected + @@ROWCOUNT
            -- 更新/新增在职人员            UPDATE dp            SET                 [Name] = td.PersonName,                Duty = td.DutyType,                Workflag = 'Y',                LastUpdate = GETDATE()            FROM syteline.SHATDB.dbo.DeptPerson dp            INNER JOIN #TempData td ON dp.PersonNo = td.PersonNo
            SET @RecordsAffected = @RecordsAffected + @@ROWCOUNT
            INSERT INTO syteline.SHATDB.dbo.DeptPerson (                PersonNo, [Name], Workflag, Duty, CreateTime, LastUpdate            )            SELECT                 td.PersonNo,                td.PersonName,                'Y',                td.DutyType,                GETDATE(),                GETDATE()            FROM #TempData td            WHERE NOT EXISTS (                SELECT 1 FROM syteline.SHATDB.dbo.DeptPerson dp                 WHERE dp.PersonNo = td.PersonNo            )
            SET @RecordsAffected = @RecordsAffected + @@ROWCOUNT        END
        -- 3. 记录日志        INSERT INTO SyncLog (SyncTime, SyncType, RecordsAffected, Status, ErrorMessage)        VALUES (GETDATE(), @SyncType@RecordsAffected@Status@ErrorMessage)
        COMMIT TRANSACTION
        -- 4. 输出结果        PRINT '同步完成!'        PRINT '类型:' + @SyncType        PRINT '耗时:' + CAST(DATEDIFF(second@StartTime, GETDATE()) AS VARCHAR+ '秒'        PRINT '处理记录数:' + CAST(@RecordsAffected AS VARCHAR)
    END TRY    BEGIN CATCH        IF @@TRANCOUNT > 0            ROLLBACK TRANSACTION
        SET @Status = 'FAILED'        SET @ErrorMessage = ERROR_MESSAGE()
        -- 记录错误日志        INSERT INTO SyncLog (SyncTime, SyncType, RecordsAffected, Status, ErrorMessage)        VALUES (GETDATE(), @SyncType0@Status@ErrorMessage)
        PRINT '同步失败:' + @ErrorMessage    END CATCH
    -- 清理临时表    IF OBJECT_ID('tempdb..#TempData'IS NOT NULL        DROP TABLE #TempDataEND

六、使用示例

-- 1. 创建链接服务器(首次使用)EXEC sp_addlinkedserver     @server = 'RemoteHR',    @provider = 'SQLOLEDB',    @datasrc = '192.168.1.100'  -- 远程服务器IP
EXEC sp_addlinkedsrvlogin     @rmtsrvname = 'RemoteHR',    @rmtuser = 'sa',    @rmtpassword = 'YourPassword'
-- 2. 测试模式(不实际执行)EXEC usp_SyncHRData @DebugMode = 1
-- 3. 正式同步所有数据EXEC usp_SyncHRData
-- 4. 只同步人员数据EXEC usp_SyncHRData @SyncType = 'PERSONNEL'
-- 5. 查看同步日志SELECT * FROM SyncLog ORDER BY SyncTime DESC

七、注意事项

问题
解决方案
远程服务器连接超时
设置超时时间:SET LOCK_TIMEOUT 30000
权限不足
检查链接服务器登录映射
性能问题
使用OPENQUERY在远程过滤数据
网络中断
添加重试机制

总结

  • OPENDATASOURCE:临时使用,配置简单

  • 链接服务器:频繁使用,性能更好

  • OPENQUERY:复杂查询,可远程过滤

  • 集合操作替代游标:性能提升10倍以上


阅读原文:原文链接


该文章在 2026/4/15 18:18:37 编辑过
关键字查询
相关文章
正在查询...
点晴ERP是一款针对中小制造业的专业生产管理软件系统,系统成熟度和易用性得到了国内大量中小企业的青睐。
点晴PMS码头管理系统主要针对港口码头集装箱与散货日常运作、调度、堆场、车队、财务费用、相关报表等业务管理,结合码头的业务特点,围绕调度、堆场作业而开发的。集技术的先进性、管理的有效性于一体,是物流码头及其他港口类企业的高效ERP管理信息系统。
点晴WMS仓储管理系统提供了货物产品管理,销售管理,采购管理,仓储管理,仓库管理,保质期管理,货位管理,库位管理,生产管理,WMS管理系统,标签打印,条形码,二维码管理,批号管理软件。
点晴免费OA是一款软件和通用服务都免费,不限功能、不限时间、不限用户的免费OA协同办公管理系统。
Copyright 2010-2026 ClickSun All Rights Reserved  粤ICP备13012886号-9  粤公网安备44030602007207号