使用存储过程将记录从 SQL Server 复制到 SQL Server (2005)

Posted

技术标签:

【中文标题】使用存储过程将记录从 SQL Server 复制到 SQL Server (2005)【英文标题】:Copy records using stored procedure from SQL Server to SQL Server ( 2005) 【发布时间】:2018-02-16 07:46:06 【问题描述】:

我有一个简单的存储过程来选择、格式化和复制 TimeCard 数据库中的记录到我们的 ERP 数据库。两者都是 SQL Server。

它作为计划作业在 SQL Server 代理上运行。代码是这样的

INSERT INTO linked_erpserver.db.SCHEMA.table01 
SELECT * 
FROM   linked_timecardserver.db.SCHEMA.tablexx X 
WHERE  X.flag = 0 

UPDATE linked_timecardserver.db.SCHEMA.tablexx 
SET    flag = 1 
WHERE  flag = 0 

现在,假设如果有大量记录并且与链接服务器的连接失败,那将是灾难性的影响。

我该如何处理?我是否应该一一选择记录,插入,更新并提交该记录。

编辑:我们使用的是 SQL Server 2005

【问题讨论】:

嗨@rauf 您是否在交易前尝试过BEGIN TRAN? -> mssqltips.com/sqlservertutorial/3305/… @AndyK 不确定这是否适用于链接的服务器。也许开始分布式事务? @Rauf:此链接也可能有帮助:***.com/questions/506602/… 此外,在尝试将其提交到您的 ERP 之前,发送到暂存表并验证暂存表是否正确会给您额外的信心。 【参考方案1】:

使用分布式事务

您需要将代码包装在事务性(全部/或全部)单元中。为了支持这一点,需要在两个 Windows/SQL Server 上安装、运行和可能配置 MSDTC 服务。然后您需要使用 BEGIN DISTRIBUTED TRANSACTION T-SQL 语法。从 SQL Server 2005 开始,您拥有使用 XACT_STATE 的魔力,而我们过去只有 XACT_ABORT,它没有提供完整的解决方案(仅失败的严重级别 16 或以上)。

XACT_STATE https://docs.microsoft.com/en-us/sql/t-sql/functions/xact-state-transact-sql

更新:这是 SQL 2005-2017 的代码:

SET XACT_ABORT ON
BEGIN DISTRIBUTED TRANSACTION;
INSERT INTO linked_erpserver.db.SCHEMA.table01 

SELECT * 
FROM   linked_timecardserver.db.SCHEMA.tablexx X 
WHERE  X.flag = 0 

UPDATE linked_timecardserver.db.SCHEMA.tablexx 
SET    flag = 1 
WHERE  flag = 0 

IF (XACT_STATE()) < 0 ROLLBACK TRANSACTION
--if XACT_STATE is 0, there is nothing to actually commit.
IF (XACT_STATE()) = 1 COMMIT TRANSACTION; 

以下链接显示了如何访问 MS DTC 配置:

https://support.resolver.com/hc/en-ca/articles/207161116-Configure-Microsoft-Distributed-Transaction-Coordinator-MSDTC-

注意: 显然,XACT_STATE 也可以返回 -2 用于除以零错误之类的事情——因此上述代码中的

https://docs.microsoft.com/en-us/azure/sql-data-warehouse/sql-data-warehouse-develop-transactions

【讨论】:

对不起,我忘了提到 SQL Server 版本。我们仍在使用 SQL Server 2005 虽然在线文档没有显示 SQL 2005 支持 XACT_STATE,但我只是通过本地安装的 SQL 2005 联机丛书验证了 SQL 2005 支持它。 如何检查是否安装了MSDTC service?不幸的是,我们没有 DBA,所以我不想对“fromDB”和“toDB”进行任何额外的安装。也就是说,我使用另一台装有 SQL Server 2005 的 PC 将数据从源数据库获取到目标数据库。【参考方案2】:

一条一条地插入记录总是被认为是一种不好的做法,但如果您在一次选择/插入中插入数百万条记录,情况也是如此。

我建议创建一个进程,一次插入 n 记录,同时将所有内容包装在事务中,以确保在该步骤中更新所有记录,或者在出现错误的情况下,没有任何记录更新了。

DECLARE @NumRecords INT
SELECT @NumRecords=COUNT(*) FROM Linked_TimeCardServer.DB.Schema.TableXX X
WHERE X.FLAG = 0

WHILE @NumRecords > 0
BEGIN
    BEGIN TRAN

    -- Get 100 Records
    SET ROWCOUNT 100

    INSERT INTO Linked_ERPServer.DB.Schema.Table01
    SELECT * FROM Linked_TimeCardServer.DB.Schema.TableXX X
    WHERE X.FLAG = 0

    If @@error <> 0 GOTO Error

    -- Update the Records that were copied
    SET ROWCOUNT 0

    Update Linked_TimeCardServer.DB.Schema.TableXX
    SET FLAG =1
    WHERE PrimareyKeyColumnId NOT IN (
        SELECT PrimareyKeyColumnId FROM Linked_ERPServer.DB.Schema.Table01
    )

    If @@error <> 0 GOTO Error

    COMMIT TRAN

    SELECT @NumRecords=COUNT(*) FROM Linked_TimeCardServer.DB.Schema.TableXX X
    WHERE X.FLAG = 0

END

Error:
    ROLLBACK TRAN

【讨论】:

以上是关于使用存储过程将记录从 SQL Server 复制到 SQL Server (2005)的主要内容,如果未能解决你的问题,请参考以下文章

调用 SQL Server 存储过程的 SqlCommand 超时

在 SQL Server 中复制数据的存储过程

将存储过程从 sql server 拉到数据库项目

如何使用 PHP 将记录从远程 SQL Server 2005 复制到本地 mySQL?

MS SQL Server - 如何将所有存储过程从我的机器导出到我的朋友机器?

将 Azure 数据工厂上的数据管道从 SQL Server 复制到 Blob 存储