使用存储过程将记录从 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 超时
如何使用 PHP 将记录从远程 SQL Server 2005 复制到本地 mySQL?