提问人:TiggerToo 提问时间:8/9/2016 最后编辑:Bill KarwinTiggerToo 更新时间:1/9/2023 访问量:2217
具有重复值和多列主键的 SQL 自动增量 ID?
SQL autoincrement id with duplicate values and multiple column primary keys?
问:
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?
谢谢
答:
不可以,除非您的 INSERT 获得表锁,否则无法执行此操作。原因是 INSERT 必须弄清楚到目前为止您要为其插入行的相应公司的最大值是多少。具有该最大值的行可以位于表中的任意位置。INSERT 必须搜索它,同时阻止任何其他 INSERT 同时运行,否则您就会遇到争用条件。
INNODB 表的 INSERT 不支持此表锁定行为。InnoDB 可以执行允许并发 INSERT 的自动增量,因为它跟踪每个表的一个最大值,并且它只递增,它不会向后移动或“撤消”递增。
MyISAM 在使用复合主键时支持按非重复值递增的功能。毕竟,MyISAM已经为INSERT或其他更新做了一个表锁。在我看来,这个功能不足以成为使用 MyISAM 的理由。
正如上面@sgeddes评论的那样,无论如何,这样做的价值是值得怀疑的。当出现间隙时,例如删除行或回滚 INSERT,您会怎么做?您是否必须对主键重新编号,这可能会更新数千行?您是否尝试将后续行插入到间隙中?这将需要另一个表锁,搜索间隙并在执行此操作时阻止其他插入。
基本上,请记住以下规则:主键不是行号。不要把它当成一个。主键必须具有唯一值,但不能具有连续值。
回复您的评论:不,您不应该认为自动递增数字有任何意义,甚至不应该认为创建顺序。首先,auto-inc 值的顺序并不总是提交行的顺序。
对 Rails 告诉你的关于数据库的任何内容都持保留态度是个好主意。Rails 的设计者真的非常非常希望数据库开发比现在更简单。在过去的 10 年里,Rails 对开发人员造成了巨大的伤害。
评论
下一个:如何为组中的每一行分配顺序值
评论
mysql
postgresql
sql-server
oracle
db2
int(20)