多个表中的唯一ID [MySQL]

时间:2010-06-12 22:02:09

标签: sql mysql

我想在两个MySQL表中创建自动增量ID(如果在第一个表中有id = 4,那么它在第二个表中不能是id = 4)。我的问题是如何以最好的方式做到这一点?

7 个答案:

答案 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_INCREMENTsession_id的类型取决于您获取唯一会话标识符的方式。

CREATE TABLE sequence 
(
  sequence_id INT NOT NULL AUTO_INCREMENT,
  session_id INT
);

每次要获取新值时,都可以执行INSERTSELECT,最后执行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,因此您最终会在其他表中出现间隙。