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