沒有簡單的方法來解決在MySQL中AUTO_INCREMENT
屬性的默認行爲,即使您找到了方法,我也不會建議您這樣做,因爲它是遇到問題的最佳方法短期。 AUTO_INCREMENT
值不意味着在生產環境中進行調整或重置。
您的問題的一個可能的解決方案可能是使您的模型稍微規範化。我們的想法是將AUTO_INCREMENT
字段移動到不需要複製或刪除行的副表。您所要做的就是在創建新項目時從此旁邊表格獲取新的id值,並在將行從一個表格複製到另一個表格時保留現有的id值。
爲了達到這個目的,我們將使用一個觸發器爲我們創建一個新的id並將其分配給我們的項目記錄。項目表的id字段必須爲空才能工作,所以我們必須用唯一索引替換主鍵。
這種模式的變化將是完全透明的爲您的應用,所以你會沒有改變在應用程序代碼做。
以下是一些示例腳本。比方說,我們已經在我們的數據庫中有兩個項目表,一些常見的行和一些行需要從第一臺到第二臺移動:
CREATE TABLE `item1` (
`id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
`item_res_id` int(11) NOT NULL DEFAULT '0',
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
CREATE TABLE `item2` (
`id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
`item_res_id` int(11) NOT NULL DEFAULT '0',
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
INSERT INTO item1 (item_res_id) VALUES (1);
INSERT INTO item1 (item_res_id) VALUES (2);
INSERT INTO item2 (item_res_id) VALUES (1);
如果我們試圖從一個表將一些數據到另一個然後重啓你的服務器,我們會遇到AUTO_INCREMENT
值重置的問題。因此,我們將稍微修改我們的模型如下:
我們將分幾個步驟進行,以將我們的數據模型。以下遷移腳本中的DDL語句已使用neXtep Designer IDE生成。
- 首先,我們創建一個新的item_keys表,將持有的
AUTO_INCREMENT
領域:
-- Creating table 'item_keys'
CREATE TABLE item_keys (
id BIGINT(20) UNSIGNED NOT NULL
,key_ctime TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP
) Engine=InnoDB default charset=utf8;
-- Creating Primary Key constraint 'PRIMARY' on table 'item_keys'
ALTER TABLE item_keys ADD CONSTRAINT PRIMARY KEY (id);
- 但激活
AUTO_INCREMENT
屬性之前,我們必須將現有的ID添加到我們的新表:
-- Initializing item_keys with existing ids
INSERT INTO item_keys (id)
SELECT i1.id
FROM item1 i1
LEFT JOIN item_keys ik ON ik.id = i1.id
WHERE ik.id IS NULL
;
INSERT INTO item_keys (id)
SELECT i2.id
FROM item2 i2
LEFT JOIN item_keys ik ON ik.id = i2.id
WHERE ik.id IS NULL
;
- 我們現在可以激活
AUTO_INCREMENT
屬性,併爲未來的刀片初始化它的價值:
-- Activating auto_increment constraint...
ALTER TABLE item_keys MODIFY id BIGINT(20) UNSIGNED NOT NULL AUTO_INCREMENT;
-- Initializing auto_increment value
SELECT @inc_value := MAX(id) FROM item_keys;
SET @alter_query = CONCAT('ALTER TABLE item_keys AUTO_INCREMENT=',@inc_value);
PREPARE alter_query FROM @alter_query;
EXECUTE alter_query;
DEALLOCATE PREPARE alter_query;
- 然後我們就可以改變
item1
和item2
表來代替由唯一索引主鍵,和引用item_keys表的主鍵:
-- De-activating auto_increment constraint...
ALTER TABLE item1 MODIFY id BIGINT(20) UNSIGNED NOT NULL;
-- Dropping constraint 'PRIMARY'...
ALTER TABLE item1 DROP PRIMARY KEY;
ALTER TABLE item1 MODIFY id BIGINT(20) UNSIGNED NULL;
-- Creating index 'item1_uk'...
CREATE UNIQUE INDEX item1_uk ON item1 (id);
-- Creating Foreign Key constraint 'item1_keys_fk' on table 'item1'
ALTER TABLE item1 ADD
CONSTRAINT item1_keys_fk FOREIGN KEY item1_keys_fk
(id) REFERENCES item_keys
(id)
;
-- De-activating auto_increment constraint...
ALTER TABLE item2 MODIFY id BIGINT(20) UNSIGNED NOT NULL;
-- Dropping constraint 'PRIMARY'...
ALTER TABLE item2 DROP PRIMARY KEY;
ALTER TABLE item2 MODIFY id BIGINT(20) UNSIGNED NULL;
-- Creating index 'item2_uk'...
CREATE UNIQUE INDEX item2_uk ON item2 (id);
-- Creating Foreign Key constraint 'item2_keys_fk' on table 'item2'
ALTER TABLE item2 ADD
CONSTRAINT item2_keys_fk FOREIGN KEY item2_keys_fk
(id) REFERENCES item_keys
(id)
;
- 最後,我們只需要創建將管理的ID創建爲我們的觸發器:
-- Creating trigger 'tr_item1_bi' on table 'item1'...
DELIMITER |;
CREATE TRIGGER tr_item1_bi BEFORE INSERT ON item1
FOR EACH ROW
BEGIN
IF (NEW.id IS NULL) THEN
-- If no item id has been specified in the INSERT statement, it
-- means we want to create a new item. We insert a new record
-- into the item_keys table to get an item id.
INSERT INTO item_keys (
key_ctime
)
VALUES (NOW());
SET NEW.id = LAST_INSERT_ID();
END IF;
END;
|;
-- Creating trigger 'tr_item2_bi' on table 'item2'...
DELIMITER |;
CREATE TRIGGER tr_item2_bi BEFORE INSERT ON item2
FOR EACH ROW
BEGIN
IF (NEW.id IS NULL) THEN
-- If no item id has been specified in the INSERT statement, it
-- means we want to create a new item. We insert a new record
-- into the item_keys table to get an item id.
INSERT INTO item_keys (
key_ctime
)
VALUES (NOW());
SET NEW.id = LAST_INSERT_ID();
END IF;
END;
|;
現在,我們可以從一個表將數據移動到另一個,保持IDS不變,如果我們重新啓動服務器,item_keys
中的AUTO_INCREMENT
值將保持不變。
--------------
INSERT INTO item2
SELECT i1.*
FROM item1 i1
LEFT JOIN item2 i2
ON i2.id = i1.id
WHERE i2.id IS NULL
--------------
Query OK, 1 row affected (0.04 sec)
Records: 1 Duplicates: 0 Warnings: 0
--------------
DELETE FROM item1
--------------
Query OK, 2 rows affected (0.00 sec)
--------------
INSERT INTO item1 (item_res_id) VALUES (3)
--------------
Query OK, 1 row affected (0.00 sec)
--------------
SELECT * FROM item1
--------------
+------+-------------+
| id | item_res_id |
+------+-------------+
| 3 | 3 |
+------+-------------+
1 row in set (0.00 sec)
--------------
SELECT * FROM item2
--------------
+------+-------------+
| id | item_res_id |
+------+-------------+
| 1 | 1 |
| 2 | 2 |
+------+-------------+
2 rows in set (0.00 sec)
--------------
SELECT * FROM item_keys
--------------
+----+---------------------+
| id | key_ctime |
+----+---------------------+
| 1 | 2010-11-14 10:31:21 |
| 2 | 2010-11-14 10:31:21 |
| 3 | 2010-11-14 10:31:46 |
+----+---------------------+
3 rows in set (0.00 sec)
MySQL 5.0不是一個版本,它的一個完整的版本系列。請提供版本的全部三位數字。如果你不知道,請'顯示像'%version%'這樣的變量'' – derobert 2010-11-10 17:33:42
另外,*我需要調整自動遞增值...在應用程序啓動時*打擊我*因爲你做錯了*。 – derobert 2010-11-10 17:54:27
爲什麼在每個論壇上都有一個人,誰知道我做錯了? :) – 2010-11-10 20:13:34