2010-06-12 60 views
2

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

+0

这将取决于您正在使用的数据库。例如,我知道PostgreSQL将允许你创建一个SEQUENCE,它应该做你想做的事。其他数据库可能有不同的方法来做到这一点。 – 2010-06-12 22:04:39

+0

@Jack:Oracle&Postgre使用序列 – 2010-06-12 23:22:15

回答

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最近也取得一些命名的雪花,你应该看看他们的GitHub的仓库

但主要是看什么做的Flickr,它的简单,可以很容易地处理

+0

OMG,这么简单... – monthon1 2010-06-14 15:52:28

+0

,但它是强大的...我前一段时间发现这个解决方案,但没有找到我的用途,因为我的应用程序是非常小的 – pastjean 2010-06-15 13:41:02

0

设置基于以下查询ID:

SELECT MAX(id) + 1 FROM table1 
UNION 
SELECT MAX(id) + 1 FROM table2 

应该工作...

+3

不,它不会。它会返回两行,每个表中最多有+ 1个值。 – Andrey 2010-06-12 22:11:19

1

任何特定的平台?

在你可以设置一个序列的种子和增量一些平台 - 在一个表中的所有甚至IDS,而在其他所有的奇数编号。

通常的反对,这是可能存在的差距,有些人不喜欢他们的代理键的差距。我个人不把很多重要的代理键值...

+0

我不想要差距......而我正在使用mysql。 – monthon1 2010-06-12 22:48:56

0

在PostgreSQL,你可以做

CREATE SEQUENCE mysequence; 

然后对于每个插入

INSERT INTO mytable values(nextval(mysequence),1,2); 
0

声明:我不是MySQL专家,某些语法可能是错误的或者改写的更好

您可以只有两列的create a table。一个用于session_id,另一个用于AUTO_INCREMENT类型的sequence_idsession_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; 
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解决方案有点复杂。因此,我们在这里检查两个表中的最大pk值(可能为null)。最大的函数(一个MySQL事物)选择最大的值,但如果其中一个或两个都为null,则结果为null。所以我们合并为0并添加1.请注意bizzaro分隔符shenanigans。这是必要的,因为MySQL开发人员是C/Perl程序员,他们认为所有事情都必须以分号结尾,因此需要在SQL中分隔符。分号偶尔终止触发器或存储过程的定义,除非您更改分隔符到别的东西 - a |在这种情况下。

为什么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) 
0

如果你能接受更改服务器中的所有表的AUTO_INCREMENT增量值,你可以绕过设置触发器的繁重工作或单独的表和whatnot:

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,所以你最终会在其他表中存在差距。