换句话说,是否保证以下“游标”方法有效:
- 从数据库中检索行
- 从返回的记录中保存最大的 ID 以供以后使用,例如
LastMax
- 之后,
"SELECT * FROM MyTable WHERE Id > {0}", LastMax
为了使它起作用,我必须确保我在步骤 1 中没有得到的每一行的 Id 都大于LastMax
. 这是有保证的,还是我会遇到奇怪的比赛条件?
换句话说,是否保证以下“游标”方法有效:
LastMax
"SELECT * FROM MyTable WHERE Id > {0}", LastMax
为了使它起作用,我必须确保我在步骤 1 中没有得到的每一行的 Id 都大于LastMax
. 这是有保证的,还是我会遇到奇怪的比赛条件?
保证绝对在任何情况下都不会获得可能小于或等于当前最大值的值?不,没有这样的保证。也就是说,这种情况可能发生的情况是有限的:
假设没有这些情况,您可以避免竞争条件造成下一个值低于现有值的情况。也就是说,不能保证行将按照其标识值的顺序提交。例如:
在提交第一个事务之前,43 存在但 42 不存在。身份列只是保留一个值,而不是规定提交的顺序。
我认为这可能会出错,具体取决于交易的持续时间考虑以下事件序列:
您的代码永远不会找到事务 A 插入的行。执行第 6 步时,它尚未提交。并且在执行下一个查询时将找不到它,因为它在标识列中的值低于查询正在查找的值。
如果您使用未提交的隔离模式执行查询,它可能会起作用
身份将始终遵循定义身份的增量:
身份[(种子,增量)] http://msdn.microsoft.com/en-us/library/aa933196(SQL.80).aspx
可以是正数或负数(您可以让它向前或向后递增)。如果您将身份设置为向前递增,您的身份值将始终大于以前的值,但如果您回滚 INSERT,您可能会错过一些。
是的,如果您将身份增量设置为正值,您的循环逻辑将起作用。
唯一可能插入的记录是您不会得到的,如果有人打开身份插入并手动将记录插入跳过的 id(或在某些情况下插入负数)。这是一种相当罕见的情况,通常只能由系统管理员完成。例如,可能会重新插入意外删除的记录。
SQL Server 唯一保证的是您的 IDENTITY 列将始终递增。
不过要考虑的事情:
这就解释了为什么 SQL Server 不保证顺序 INDENTITY。
有一种方法可以使用DBCC命令重置 IDENTITY 列。但在此之前,请考虑以下事项:
IDENTITY 列是 DBRM 中永远不会更改的最重要元素之一。
这是一个可以帮助您的链接:了解 IDENTITY 列
编辑: 您似乎所做的工作将作为 LastMax 的 IDENTITY 列将始终为每个 INSERTed 行递增。所以:
- 从数据表中选择行;
- 保存 LastMax 状态;
- 选择 Id > LastMax 的行。
3) 将只选择 IDENTITY 列将大于 LastMax 的行,因此在保存 LastMax 后插入。