我可以在 while reader.read 循环中间从 sql server 表中删除记录吗
我正在尝试使用 SQL 数据读取器将记录从一个表移动到存档表中。我想逐条记录地传输(而不是批量插入和删除),以便如果发生错误,丢失的数据量最少(并且必须从备份中恢复)。
我的问题是,如果我在读取记录后删除记录,SQL 阅读器会工作吗?这是迄今为止最简单、最直接的方法来完成我想做的事情。它会打开意外错误吗?
While myReader.Read // select * from tableA where older than 1 year record
insert the record into tableA_archive
delete the record from tableA
loop
这似乎隐约类似于循环遍历您在循环中修改的列表——我知道这会导致 .net 中的各种令人头疼的问题。
for aItem in listA
if aItem fits criteria, send to list B and delete from listA
next
当读者阅读时,有什么理由不修改基础表?例如,如果我在循环中间开始删除记录,读者是否会使用某些索引来访问可能会发生变化的记录?
I am trying to using a SQL data reader to move records from one table into an archive table. I want to do the transfer record-by-record (instead of inserting and deleting en masse) so that if an error occurs, the minimum amount of data is lost (and has to be restored from backup).
My question is, will SQL reader work if I delete records once they are read? This is by far the most simple and direct way to do what I am trying to do. Will it open unexpected errors?
While myReader.Read // select * from tableA where older than 1 year record
insert the record into tableA_archive
delete the record from tableA
loop
This seems vaguely analogous to looping through a list that you are modifying within the loop--which I know causes all sorts of headaches in .net
for aItem in listA
if aItem fits criteria, send to list B and delete from listA
next
Is there any reason not to modify the underlying table while a reader is reading? For instance, does a reader use certain indexes to reach records that might shift if I start deleting records in the middle of the loop?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
您应该避免将行一直传输到客户端,而只是将它们重新上传回服务器。相反,执行如下操作(在同一事务内):
或者甚至是 MS SQL Server 特定的:
(所有条件都相同)
如果您愿意,您甚至可以从 .NET 代码中执行这些语句,并且仍然保留不下载所有行的好处。
You should avoid transferring rows all the way down to the client, just to re-upload them back to the server again. Instead, do something like this (within the same transaction):
Or even MS SQL Server specific:
(all conditions are same)
You can even execute these statements from your .NET code if you wish, and still retain the benefit of not downloading all the rows.
您应该花一些时间阅读事务隔离,特别是可重复读取。
在 SQL Server 中,select 语句(支持您的读取器)(默认情况下)在 READ COMMITTED 隔离中执行,这意味着您的删除命令将能够在读取行后删除这些行,但行集当执行 select 语句时,读取器读取的数据不能被删除语句修改。
无论如何,将数据从一个表移动到另一个表通常应该在 SQL 中完成,而不是在 .NET 中完成。
You should spend some time reading about transactional isolation, specifically repeatable reads.
In SQL Server, a select statement (which backs your reader) executes (by default) in READ COMMITTED isolation, which means that your delete command will be able to delete rows after they are read, but the set of the rows that the reader reads cannot be modified by a delete statement while the select statement is executing.
For what it is worth, moving data from one table to another should generally be done in SQL, not in .NET.
有几种方法,首先你必须了解什么是事务隔离
在 SQL Server 中以及什么时候需要使用它。
在您的情况下,似乎您正在将历史数据移动到另一个表,因此在事务范围内使用 SQL 存储过程(带有回滚事务)是值得的。
There are several way on these, first you have to understand what is transaction isolation
in SQL server and when do you need to use that.
In your case, seems like you are moving historical data to another table, so using SQL Stored Procedure within transaction scope(with rollback trans) would be worth it.
您应该在事务中执行此操作。这也是一个非常好的 SP 候选者,尽管您也可以在代码中做到这一点。您必须找到一个能够产生相当数量的行的条件(不是 1,而是可能是 100、1000 或 10000)。实验并找出在合理的时间内(可能是几秒钟)在一个语句中可以插入和删除多少个。
SomeCondition 可以是日期范围(例如一天、一小时等)。
然后循环运行此过程,更改 SomeCondition,直到没有任何内容可备份。由于这是在事务内,因此插入和删除都会成功或失败。
不管你想一次删除多少个,如果你关心一致性,你就必须在一个事务中完成。
You should do it within a transaction. This also is a very good candidate for a SP even though you could do it in the code also. You will have to find out a condition that results in a decent amount of rows (not 1 but may be 100 or 1000 or 10000). Experiment and find out how many can be inserted and deleted in one statement within reasonable time (may be few seconds).
SomeCondition could be a date range (say a day, an hr etc).
Then run this process in a loop changing the SomeCondition until there is nothing to be backed up. Since this is within a transaction, both insert and delete would either succeed or fail.
Regardless of how many you want to delete in one, if you are concerned about the consistancy, you have to do it within a transaction.