作为存档过程的一部分,我正在将记录从一个数据库移动到另一个数据库。我想将行复制到目标表,然后从源表中删除相同的行。
我的问题是,在删除行之前检查第一次插入是否成功的最有效方法是什么。
我的想法是这样,但我觉得有更好的方法:
@num_records=select count(ID) from Source_Table where (criteria for eligible rows)
insert * into Destination_Table where (criteria for eligible rows)
if ((select count(ID) from Destination_Table where (criteria) )=@numrecords)
delete * from Source_Table where (criteria)
Run Code Online (Sandbox Code Playgroud)
将它与 RAISERROR 功能结合是否更好/可能?谢谢!
Mar*_*ith 19
如果您的存档表没有。
你也可以在一份声明中做到这一点。
DELETE FROM source_table
OUTPUT deleted.Foo,
deleted.Bar,
SYSUTCDATETIME()
INTO archive_table(Foo, Bar, archived)
WHERE Foo = 1;
Run Code Online (Sandbox Code Playgroud)
这将作为一个单元成功或失败,并且还避免了可能的竞争条件,因为在INSERT
存档和之间添加了行DELETE
(尽管您的WHERE
子句很可能使这种情况变得极不可能)。
Mik*_*Fal 13
我会推荐TRY/CATCH语法以及显式事务。我对此解决方案的假设是,插入失败的原因是某种可捕获的 SQL 错误(例如键违规、数据类型不匹配/转换错误等)。结构如下所示:
BEGIN TRAN
BEGIN TRY
INSERT INTO foo(col_a,col_b,col_c,recdate)
SELECT col_a,col_b,col_c,recdate
FROM bar
WHERE recdate BETWEEN @startdate AND @enddate
DELETE FROM bar
WHERE recdate BETWEEN @startdate AND @enddate
COMMIT TRAN
END TRY
BEGIN CATCH
ROLLBACK TRAN
END CATCH
Run Code Online (Sandbox Code Playgroud)
这种结构的工作方式是,如果 INSERT 或 DELETE 中发生任何错误,整个操作都会回滚。这保证了整个动作必须成功完成。如果您觉得有必要,您可以将其与2012 年的THROW或2008 年及之前的RAISERROR结合起来,以添加额外的逻辑并在不满足该逻辑的情况下强制回滚。
另一种选择是查看SET XACT_ABORT ON,尽管我觉得 TRY/CATCH 语法为您提供了更多的粒度。
归档时间: |
|
查看次数: |
25481 次 |
最近记录: |