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

具有重复值和多列主键的SQL自动增量id?

  •  2
  • TiggerToo  · 技术社区  · 8 年前
    CREATE TABLE Apps
    (
        id int NOT NULL,
        company varChar(20) NOT NULL,
        name varChar(20) NOT NULL,
        CONSTRAINT company_app_id PRIMARY KEY (id, company)
    )
    
    -------------------------------------
    | id  | company      | name         |
    -------------------------------------
    |  1  | Google       | Google Maps  |
    |  2  | Google       | Gmail        |
    |  1  | Apple        | Safari       |
    |  3  | Google       | Chrome       |
    |  2  | Apple        | Pages        |
    -------------------------------------
    

    SQL中是否有一种方法可以构建上面的表,允许它自动增加特定于公司的id?因此,如果下一个条目是Google应用程序,它会自动将id递增为4,如果后面的条目是Apply应用程序,则会自动将id递增为2?

    1 回复  |  直到 8 年前
        1
  •  3
  •   Bill Karwin    8 年前

    不,除非INSERT执行表锁,否则无法执行此操作。原因是INSERT必须计算到目前为止您要为其插入一行的各个公司的最大值。具有最大值的行可以在表中的任何位置。INSERT必须在防止任何其他INSERT并发运行的同时搜索它,否则会出现争用条件。

    INSERT对InnoDB表不支持此表锁定行为。InnoDB可以执行自动递增,只允许并发INSERT,因为它跟踪每个表的一个最大值,并且只递增,不会向后移动或“撤消”递增。

    当使用复合主键时,MyISAM支持按不同值递增的功能。毕竟,MyISAM已经为INSERT或其他更新做了表锁。在我看来,这一特性不足以证明使用MyISAM的正当性。

    正如@sgeddes上面所评论的,这样做的价值无论如何都值得怀疑。当出现间隙时,例如删除一行或回滚INSERT时,您会怎么做?是否必须对主键重新编号,从而可能更新数千行?是否尝试将后续行插入间隙?这将需要另一个表锁,在执行此操作时搜索间隙并阻止其他插入。

    主键不是行号。 不要把它当一回事。主键必须具有唯一值,但不能是连续值。


    关于你的评论:不,你不应该认为自动递增的数字有任何意义,甚至连创建的顺序都没有。首先,auto inc值的顺序并不总是提交行的顺序。

    最好对Rails告诉您的关于数据库的任何信息都持保留态度。Rails的设计者真的、真的希望数据库开发比现在更简单。Rails在过去10年里给开发人员带来了巨大的伤害。