2017-08-09 74 views
0

行,所以我有如下表:對重複關鍵詞追加行

CREATE TABLE `Tags` (
    `tag_id` int(10) unsigned NOT NULL AUTO_INCREMENT, 
    `tag` varchar(100) DEFAULT NULL, 
    PRIMARY KEY (`tag_id`), 
    UNIQUE KEY `tag` (`tag`), 
    KEY `tag_id` (`tag_id`) 
) ENGINE=InnoDB AUTO_INCREMENT=0 DEFAULT CHARSET=utf8; 
SET FOREIGN_KEY_CHECKS=1; 

當我運行下面的查詢,它似乎是增加了主鍵,即使它找到重複的(即使它不添加重複)。

INSERT INTO Tags (tag) VALUES ('book'),('cats'),('dogs') ON DUPLICATE KEY UPDATE tag = tag 

結果...

tag_id | tag 
============================== 
1  | book 
2  | robots 
3  | doodles 
5  | cats 
6  | dogs 
============================== 

如何避免這種情況?

+1

沒有什麼可以阻止的。 「auto_increment」的數量已用完。他們從未被重用。這就是它的工作原理,如果它看起來「愚蠢」 - 事實並非如此。如果你試圖「解決」這個問題,你實際上會受到傷害。此外,查詢看起來不合適,它看起來好像您在「INSERT IGNORE」之後。 –

回答

2

你不能真的防止這一點,你不應該擔心。自動遞增的ID中的差距幾乎從來都不是問題。

發生了什麼是MySQL試圖插入該行。爲了插入行,它必須構造它 - 因此自動遞增的列會增加。當行已經找到時,插入失敗,但自動遞增已經增加。

如果你想最大限度地減少問題,你可以嘗試找到重複之前試圖插入:

INSERT INTO Tags (tag) 
    SELECT t.tag 
    FROM (SELECT 'book' as tag UNION ALL 
      SELECT 'cats' as tag UNION ALL 
      SELECT 'dogs' as tag 
     ) t 
    WHERE NOT EXISTS (SELECT 1 FROM Tags t2 WHERE t2.tag = t.tag) 
    ON DUPLICATE KEY UPDATE tag = VALUES(tag); 

這不是一個100%修復 - 子查詢可能有重複或其他進程可以在運行時更新表格。但是,它通常會避免插入不應插入的記錄。

+0

感謝您的解釋。這是有道理的。我將不得不修改我的程序,除非必要,否則不會執行這些添加,否則我可能會得到一個非常大的主鍵表。回到繪圖板:) – Hugo

+1

@Hugo - 讓你的pk bigint可以給你一系列'2^64 - 1'。即使你每秒浪費幾千個鑰匙,你也應該可以過上幾千年的時間:) – Mjh

1

結賬innodb_autoinc_lock_mode。它目前的設置是什麼?設置innodb_autoinc_lock_mode = 0可能會給你你想要的,但它默認爲1

此外,您的密鑰tag_idtag_id)是多餘的,因爲這已經是您的主要密鑰。

+0

感謝您的提示!將修改! – Hugo