代码之家  ›  专栏  ›  技术社区  ›  balpha

SQL Server是否保证按顺序插入标识列?

  •  12
  • balpha  · 技术社区  · 14 年前

    换言之,是否保证以下“诅咒”方法有效:

    1. 从数据库中检索行
    2. 从返回的记录中保存最大的ID供以后使用,例如 LastMax
    3. 后来, "SELECT * FROM MyTable WHERE Id > {0}", LastMax

    为了让它起作用,我必须确保 每一排我没有进入第一步 ID大于 拉斯特马克斯 . 这是有保证的,还是我会遇到奇怪的比赛条件?

    5 回复  |  直到 14 年前
        1
  •  17
  •   Thomas    14 年前

    绝对保证在任何情况下,你都不可能得到一个可能小于或等于当前最大值的值?不,没有这样的保证。也就是说,这种情况可能发生的情况是有限的:

    1. 有人禁用标识插入并插入一个值。
    2. 有人重新设置了标识列。
    3. 有人更改了增量值的符号(即,不是+1而是-1)

    假设没有这些情况,您就可以安全地避开竞争条件,从而创建下一个值低于现有值的情况。也就是说,不能保证 坚信的 按照他们的身份价值的顺序。例如:

    1. 打开事务,使用标识列插入到表中。假设它得到值42。
    2. 在同一个表中插入并提交另一个值。假设它得到值43。

    在提交第一个事务之前,43个事务存在,42个事务不存在。Identity列只是保留一个值,而不是指定提交的顺序。

        2
  •  4
  •   Wolfgang    14 年前

    我认为这可能会出错,这取决于交易的持续时间 考虑以下事件序列:

    1. 事务A启动
    2. 事务A执行插入-这将在标识列中创建一个新条目
    3. 事务B启动
    4. 事务B执行插入-这将在标识列中创建一个新条目
    5. 交易B承诺
    6. 您的代码执行其选择并查看第二个事务的标识值
    7. 事务A提交-

    您的代码将永远找不到事务A插入的行。执行步骤6时尚未提交。当执行下一个查询时,将找不到它,因为标识列中的值比查询要查找的值低。

    如果使用 read-uncommitted 隔离模式

        3
  •  2
  •   KM.    14 年前

    标识将始终遵循定义标识的增量:

    标识[(种子,增量)] http://msdn.microsoft.com/en-us/library/aa933196(SQL.80).aspx

    可以是正的也可以是负的(可以向前或向后递增)。如果将标识设置为向前递增,则标识值将始终大于前一个值,但如果回滚插入,则可能会丢失一些值。

    是的,如果将标识增量设置为正值,则循环逻辑将工作。

        4
  •  1
  •   HLGEM    14 年前

    唯一可能无法插入的时间记录是,如果有人打开标识插入并手动将记录插入跳过的ID(或在某些情况下插入负数)。这是一种相当罕见的情况,通常只能由系统管理员完成。例如,可以重新插入意外删除的记录。

        5
  •  0
  •   Will Marcouiller    14 年前

    SQL Server唯一保证的是,您的标识列将始终递增。

    但是需要考虑的事情是:

    1. 如果插入失败,则标识列无论如何都将递增;
    2. 如果发生回滚,标识列将不会返回到其先前的值;

    这就解释了为什么SQL Server不保证顺序缩进。

    有一种方法可以使用 DBCC 命令。但在此之前,请考虑以下事项:

    1. 确保您的标识列没有被任何其他表引用,因为您的外键不能用它更新,所以前面有很大的麻烦;
    2. 您可以使用 SET IDENTITY_INSERT ON/OFF 指令,以便您可以在插入行时手动指定标识(以后永远不要忘记打开它)。

    标识列是dbrms中不可更改的最重要元素之一。

    这里有一个链接可以帮助您: Understanding IDENTITY columns

    编辑: 您似乎要做的工作是,lastmax中的标识列将始终为每个插入行递增。所以:

    1. 从数据表中选择行;
    2. 保存lastmax状态;
    3. 选择id>lastmax所在的行。

    3)将只选择标识列大于lastmax的行,因此在保存lastmax之后插入。