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

dly7yett  于 2023-01-12  发布在  Mysql
关注(0)|答案(1)|浏览(122)
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?
谢谢

2ul0zpep

2ul0zpep1#

不,除非INSERT获得了表锁,否则无法执行此操作。原因是INSERT必须计算出您要插入行的各个公司到目前为止的最大值。具有该最大值的行可能在表中的任何位置。INSERT必须在搜索该行的同时防止任何其他INSERT并发运行,否则就会出现争用条件。
INSERT到InnoDB表不支持这种表锁行为。InnoDB可以执行允许并发INSERT的自动递增,这是因为它跟踪每个表的一个最大值,并且它只递增,它不向后移动或"撤消"递增。
MyISAM在使用复合主键时支持按不同值递增的特性。毕竟,MyISAM已经为INSERT或其他更新做了表锁。在我看来,这个特性不足以成为使用MyISAM的理由。
正如@sgeddes上面所评论的,这样做的价值是值得怀疑的。当出现间隙时,例如,如果删除了一行或者回滚INSERT,您该怎么办?您是否必须重新编号主键,从而可能更新数千行?您是否尝试将后续行插入间隙中?这将需要另一个表锁,在您执行此操作时搜索间隙并阻止其他插入。
基本上,请记住这条规则:* * 主键不是行号。**不要将其视为行号。主键要求具有唯一值,但不能具有连续值。
回复您的评论:不,您不应该认为自动递增的数字有任何意义,甚至创建的顺序也没有意义。首先,自动递增值的顺序并不总是提交行的顺序。
对Rails告诉你的关于数据库的任何事情都持保留态度是一个好主意。Rails的设计者真的真的希望数据库开发比现在更简单。在过去的10年里,Rails给开发人员带来了巨大的伤害。

相关问题