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

SQL autoincrement id with duplicate values and multiple column primary keys?

提问人:TiggerToo 提问时间:8/9/2016 最后编辑:Bill KarwinTiggerToo 更新时间:1/9/2023 访问量:2217

问:

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,如果之后的条目是应用应用,则会自动将 id 递增为 2?

谢谢

MySQL SQL 自动增量

评论

0赞 marc_s 8/9/2016
这是针对哪个 RDBMS?请添加一个标签来指定您使用的是 、 、 还是 - 或完全其他的东西。mysqlpostgresqlsql-serveroracledb2
1赞 Bill Karwin 8/9/2016
我推断它是MySQL。线索是.int(20)
1赞 sgeddes 8/9/2016
你可以,但我看不出它有什么好处。这可能是一个令人头疼的管理问题。只需使用常规的自动增量字段,然后将此逻辑构建到视图中,如果这就是您需要它的原因。
0赞 datagod 8/9/2016
您的公司名称应位于其自己的表 Company 中,并带有自动递增的整数 PK。然后,您的 Apps 表将具有 CountryID 作为 FK 引用公司。
0赞 TiggerToo 8/9/2016
这是一个设计文档。SQL的版本尚未确定。不过倾向于极光。

答:

4赞 Bill Karwin 8/9/2016 #1

不可以,除非您的 INSERT 获得表锁,否则无法执行此操作。原因是 INSERT 必须弄清楚到目前为止您要为其插入行的相应公司的最大值是多少。具有该最大值的行可以位于表中的任意位置。INSERT 必须搜索它,同时阻止任何其他 INSERT 同时运行,否则您就会遇到争用条件。

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

MyISAM 在使用复合主键时支持按非重复值递增的功能。毕竟,MyISAM已经为INSERT或其他更新做了一个表锁。在我看来,这个功能不足以成为使用 MyISAM 的理由。

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

基本上,请记住以下规则:主键不是行号。不要把它当成一个。主键必须具有唯一值,但不能具有连续值。


回复您的评论:不,您不应该认为自动递增数字有任何意义,甚至不应该认为创建顺序。首先,auto-inc 值的顺序并不总是提交行的顺序。

对 Rails 告诉你的关于数据库的任何内容都持保留态度是个好主意。Rails 的设计者真的非常非常希望数据库开发比现在更简单。在过去的 10 年里,Rails 对开发人员造成了巨大的伤害。

评论

0赞 TiggerToo 8/9/2016
难道不是不言而喻的,仅仅因为你删除了一个条目,ID就不会被重用吗?也许我在这里的想法有太多的 Rails 偏见,但我认为 id 是一种与时间无关的时间戳,它指示了创建顺序。
4赞 Mjh 8/9/2016
@TiggerToo - 事实并非如此。它是唯一的标识符。它除了不能重复使用它们,你不能填补空白,你不能强迫它按公司递增,你不能预测它的价值之外,它什么也没做。它所做的只是在并发环境中为行提供一些独特的东西,在该环境中,许多连接“竞争”这样的值。它的行为是有充分理由的,这个原因是并发+性能,这是实现这种功能的唯一方法。如果您需要其他内容,请实现以某种方式枚举记录的过程。
0赞 Monero Jeanniton 1/8/2023
PS:请检查此参考以了解如何将约束应用于顺序 ID:stackoverflow.com/questions/60526982/...