【问题标题】:identity column in Sql serverSql server 中的标识列
【发布时间】:2011-02-22 20:04:23
【问题描述】:

为什么Sql server 不允许在一张表中有多个IDENTITY 列??任何具体原因。

【问题讨论】:

  • 接受的答案是错误的原因。即使它允许您创建两个身份列,尽管as here

标签: sql sql-server


【解决方案1】:

你为什么需要它? SQL Server 为每个具有IDENTITY 列的表跟踪单个值(当前标识值),因此每个表只能有一个标识列。

【讨论】:

    【解决方案2】:

    身份列是数据库表中的一列(也称为字段):-

    1. 唯一标识表中的每一行
    2. 由数据库生成的值组成

    这很像 Microsoft Access 中的自动编号字段或 Oracle 中的序列。

    标识列与主键的不同之处在于它的值由服务器管理并且(除了极少数情况)不能修改。在许多情况下,标识列用作主键,但并非总是如此。

    SQL 服务器使用标识列作为键值来引用特定行。所以只能创建一个标识列。此外,如果没有明确声明标识列,Sql server 会在内部存储一个单独的列,其中包含每行的键值。如前所述,如果您希望多个列具有唯一值,则可以使用 UNIQUE 关键字。

    【讨论】:

    • “一个标识列...唯一标识表中的每一行”——真的吗?那为什么这可能呢?: CREATE TABLE Test1 (col1 INTEGER IDENTITY) ; SET IDENTITY_INSERT Test1 ON ;插入到 Test1 (col1) 值 (1) ;插入到 Test1 (col1) 值 (1) ; SET IDENTITY_INSERT Test1 关闭;从 Test1 中选择 col1
    • ...因此,如果 SQL Server 允许 IDENTITY 列包含重复项,那么“SQL Server 使用标识列作为键值来引用特定行”怎么可能是真的呢?
    • 有一天,你的 cmets 没有意义了。 SQL Server 不允许标识列包含重复项。
    • @Lisa - 是的。这在第一条评论中得到了证明。 “如果没有明确说明标识列,Sql server 在内部存储一个单独的列,其中包含每一行的键值”。这完全是错误的。我假设您正在考虑添加到非唯一聚集索引的唯一符。有人问了这个答案here
    【解决方案3】:

    SQL Server 将标识存储在内部表中,使用表的 id 作为键。因此,SQL Server 不可能在每个表中拥有多个 Identity 列。

    【讨论】:

      【解决方案4】:

      因为 MS 意识到,超过 80% 的用户只希望每个表有一个自动增量列,而拥有第二个(或更多)的解决方法很简单,即创建一个 IDENTITY,种子 = 1,增量 = 1 然后计算列将自动生成的值乘以一个因子以更改增量并添加偏移量以更改种子。

      【讨论】:

        【解决方案5】:

        是的,Sequences 允许多个身份,例如 atable 中的列,但这里存在一些问题。在典型的开发场景中,我看到开发人员在列中手动插入有效值(假设是通过序列插入)。稍后当一个序列尝试向表中插入值时,它可能会由于唯一键冲突而失败。

        此外,在多开发人员/多供应商的情况下,开发人员可能对多个表使用相同的序列(因为序列未链接到表)。这可能会导致其中一个表中的值缺失。即 tableA 可能会得到值 1,而 tableB 可能会使用值 2,而 tableA 会得到 3。这意味着 tableA 将有 1 和 3(缺少 2)。

        除此之外,还有另一种情况,您有一个每天都会被截断的表。由于序列与 table 没有任何链接,因此截断的表将继续使用 Seq.NextVal 再次(除非您手动重置序列),从而在一段时间后导致缺失值甚至更危险的算术溢出错误。

        由于上述原因,我觉得 Oracle 序列和 SQL 服务器标识列都适合它们的用途。我更喜欢 oracle 实现标识列的概念和 SQL Server 实现序列概念,以便开发人员可以根据需要实现两者中的任何一个。

        【讨论】:

        • 这个问题询问的是标识列,而不是序列对象(现在从 SQL Server 2012 开始提供)。
        【解决方案6】:

        标识列的全部目的是它将包含表中每一行的唯一值。那么,为什么在任何给定的表中都需要不止一个呢?

        如果您确实需要不止一个,也许您需要澄清您的问题。

        【讨论】:

        • 真的吗?那为什么这可能呢?: CREATE TABLE Test1 (col1 INTEGER IDENTITY) ; SET IDENTITY_INSERT Test1 ON ;插入到 Test1 (col1) 值 (1) ;插入到 Test1 (col1) 值 (1) ; SET IDENTITY_INSERT Test1 关闭;从 Test1 中选择 col1 ;
        【解决方案7】:

        标识列用于唯一标识表的单行。如果您希望其他列是唯一的,您可以为您可能需要的每个“身份”列创建一个 UNIQUE 索引。

        【讨论】:

        • 真的吗?那为什么这可能呢?: CREATE TABLE Test1 (col1 INTEGER IDENTITY) ; SET IDENTITY_INSERT Test1 ON ;插入到 Test1 (col1) 值 (1) ;插入到 Test1 (col1) 值 (1) ; SET IDENTITY_INSERT Test1 关闭;从 Test1 中选择 col1
        【解决方案8】:

        我一直认为这是对 SQL Server 的任意且不好的限制。是的,您只需要一个标识列来实际标识一行,但是有正当理由希望数据库为数据库中的多个字段自动生成一个数字。

        这就是 Oracle 中序列的好处。它们没有绑在桌子上。您可以使用几个不同的序列在同一个表中填充任意数量的字段。您也可以让多个表共享相同的序列,尽管这可能是一个非常糟糕的决定。但关键是你可以。它更精细,为您提供更大的灵活性。

        序列的坏处是您必须编写代码来实际递增它们,无论是在您的插入语句中还是在表上的插入触发器中。 SQL Server 标识的好处在于,您所要做的就是更改属性或在表创建中添加关键字,然后就完成了。

        【讨论】:

        • 呃,这是两个完全不同的东西。 On 是身份的概念,它可以由生成的序列管理。另一个是生成的序列。抱怨一个人并不值得对另一个人产生不好的感觉。
        • 99.9% 的情况下,SQL Server IDENTITY 列和 Oracle 序列用于相同目的:作为数据库生成的键来为行提供唯一性。但是,您可以以无法使用 IDENTITY 列的其他方式使用 Oracle 序列。我指出其他数据库供应商认识到需要能够为表中的多个字段自动生成值,而 SQL Server 没有。问题的作者似乎对此感到困惑和不安,我同意这种观点。
        猜你喜欢
        • 1970-01-01
        • 2021-08-03
        • 1970-01-01
        • 2010-10-14
        • 1970-01-01
        • 1970-01-01
        • 2013-06-08
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多