2010-06-12 64 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,所以你最終會在其他表中存在差距。