我想在两个MySQL表中创建自动增量ID(如果在第一个表中有id = 4,那么它在第二个表中不能是id = 4)。我的问题是如何以最好的方式做到这一点?
答案 0 :(得分:2)
您需要的是外部生成的序列并将其链接到您的2个表
你应该看看flickr做了什么,看看这个链接:http://code.flickr.com/blog/2010/02/08/ticket-servers-distributed-unique-primary-keys-on-the-cheap/
您创建了生成id:
的表CREATE TABLE `Tickets64` (
`id` bigint(20) unsigned NOT NULL auto_increment,
`stub` char(1) NOT NULL default '',
PRIMARY KEY (`id`),
UNIQUE KEY `stub` (`stub`)
) ENGINE=MyISAM
并获得你喜欢的新ID:
REPLACE INTO Tickets64 (stub) VALUES ('a');
SELECT LAST_INSERT_ID();
Twitter最近还发了一些名为snowflake的东西,你应该看看他们的github存储库
但主要看看flickr做了什么,它更简单,可以轻松处理
答案 1 :(得分:1)
任何特定的平台?
在某些平台中,您可以设置序列的种子和增量 - 在一个表中包含所有偶数ID,在另一个表中包含所有奇数ID。
通常的反对意见是可能存在差距,有些人不喜欢代理键中的空白。我个人并不太重视代理键值...
答案 2 :(得分:0)
根据以下查询设置ID:
SELECT MAX(id) + 1 FROM table1
UNION
SELECT MAX(id) + 1 FROM table2
应该工作......
答案 3 :(得分:0)
在PostgreSQL中,你可以做到
CREATE SEQUENCE mysequence;
然后为每个插入
INSERT INTO mytable values(nextval(mysequence),1,2);
答案 4 :(得分:0)
免责声明:我不是MySQL专家,有些语法错误或重写得更好
您只能使用两列create a table。一个用于session_id
,另一个用于sequence_id
类型AUTO_INCREMENT
。 session_id
的类型取决于您获取唯一会话标识符的方式。
CREATE TABLE sequence
(
sequence_id INT NOT NULL AUTO_INCREMENT,
session_id INT
);
每次要获取新值时,都可以执行INSERT
,SELECT
,最后执行DELETE
:
INSERT INTO sequence (session_id) VALUES (?);
SELECT sequence_id FROM sequence WHERE session_id = ?;
DELETE FROM sequence WHERE session_id = ?;
另一种方法是使用SAVEPOINT and ROLLBACK TO
,但如果它能在所有MySQL安装上运行,我就不会说它了:
START TRANSACTION WITH CONSISTENT SNAPSHOT;
SAVEPOINT next_value;
INSERT INTO sequence (session_id) VALUES (?);
SELECT sequence_id FROM sequence WHERE session_id = ?;
ROLLBACK TO next_value;
答案 5 :(得分:0)
好的,这就是答案 - 它有效,我在MySQL中进行了测试。
create table tab1 (
pk int not null default 0 primary key,
col char(1) not null
);
create table tab2 (
pk int not null default 0 primary key,
col char(1) not null
);
delimiter |
create trigger tab1_pk before insert on tab1
for each row begin
set new.pk = greatest(coalesce((select max(pk) from tab1), 0),
coalesce((select max(pk) from tab2), 0)) + 1;
end;
|
delimiter |
create trigger tab2_pk before insert on tab2
for each row begin
set new.pk = greatest(coalesce((select max(pk) from tab1), 0),
coalesce((select max(pk) from tab2), 0)) + 1;
end;
|
delimiter ;
与MySQL一样,解决方案有点令人费解。所以这里我们检查两个表中的max pk值(可能为null)。最大的函数(MySQL事物)选择最大值,但如果其中一个或两个都为空,则结果为null。因此我们合并到0并添加1.注意bizzaro定界符shenanigans。这是必要的,因为MySQL开发人员认为所有事情都必须以分号结束,因此需要在SQL中使用分隔符。分号会提前终止触发器或存储过程的定义,除非您更改分隔符别的东西 - 一个|在这种情况下。
为什么MySQL如此受欢迎?我想这就像问为什么PHP,Perl和Java一样 - 呃。
无论如何,现在离开咆哮箱是这样的测试:
dbserver/mydb> insert tab1(col) values('a');
Query OK, 1 row affected (0.06 sec)
dbserver/mydb> select * from tab1;
+----+-----+
| pk | col |
+----+-----+
| 1 | a |
+----+-----+
1 row in set (0.00 sec)
dbserver/mydb> insert tab1(col) values('b');
Query OK, 1 row affected (0.05 sec)
dbserver/mydb> select * from tab1;
+----+-----+
| pk | col |
+----+-----+
| 1 | a |
| 2 | b |
+----+-----+
2 rows in set (0.00 sec)
dbserver/mydb> insert tab2(col) values('a');
Query OK, 1 row affected (0.07 sec)
dbserver/mydb> select * from tab2;
+----+-----+
| pk | col |
+----+-----+
| 3 | a |
+----+-----+
1 row in set (0.00 sec)
dbserver/mydb> insert tab1(col) values('c');
Query OK, 1 row affected (0.07 sec)
dbserver/mydb> select * from tab1;
+----+-----+
| pk | col |
+----+-----+
| 1 | a |
| 2 | b |
| 4 | c |
+----+-----+
3 rows in set (0.00 sec)
dbserver/mydb> insert tab2(col) values('b');
Query OK, 1 row affected (0.05 sec)
dbserver/mydb> select * from tab2;
+----+-----+
| pk | col |
+----+-----+
| 3 | a |
| 5 | b |
+----+-----+
2 rows in set (0.00 sec)
答案 6 :(得分:0)
如果您可以接受更改服务器中所有表的auto_increment增量值,则可以绕过设置触发器或单独表等繁重的工作:
create table a (...);
create table b (...);
alter table a set auto_increment=1;
alter table b set auto_increment=2;
set @@auto_increment_increment=2;
之后,您将在表'a'中使用奇数ID,甚至在表'b'中使用ID。
当然,缺点是更改此变量会影响所有auto_increments,因此您最终会在其他表中出现间隙。