Es gibt keinen einfachen Weg, um das AUTO_INCREMENT
Attribut Standardverhalten in MySQL zu umgehen, und selbst wenn Sie einen Weg finden, würde ich Ihnen nicht empfehlen, dies zu tun, da es der beste Weg ist, um Probleme zu finden kurzfristig. AUTO_INCREMENT
Werte sollen in einer Produktionsumgebung nicht angepasst oder zurückgesetzt werden.
Eine mögliche Lösung für Ihr Problem könnte sein, Ihr Modell ein wenig zu denormalisieren. Die Idee ist, das Feld AUTO_INCREMENT
in eine Seitentabelle zu verschieben, wo Sie keine Zeilen kopieren oder löschen müssen. Sie müssen dann nur einen neuen ID-Wert aus dieser Seitentabelle abrufen, wenn Sie ein neues Element erstellen, und den vorhandenen ID-Wert beibehalten, wenn Sie Zeilen von einer Tabelle in eine andere kopieren.
Um dies zu erreichen, verwenden wir einen Trigger, der eine neue ID für uns erstellt und sie unserem Artikeldatensatz zuweist. Das ID-Feld der Item-Tabelle muss nullbar sein, damit dies funktioniert. Daher müssen wir den Primärschlüssel durch einen eindeutigen Index ersetzen.
Diese Modellwechsel vollständig transparent für Ihre Anwendung wäre, so würden Sie keine Änderung in Ihrem Anwendungscode zu machen.
Hier sind einige Beispielskripte. Lassen Sie uns sagen, dass wir zwei Postentabellen in unserer Datenbank haben, mit einigen gemeinsamen Zeilen und einige Zeilen, die von der ersten Tabelle auf den zweiten Tisch bewegt werden müssen:
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);
Wenn wir versuchen, einige Daten von einem Tisch zum anderen zu bewegen und dann starten Sie Ihren Server neu, wir werden das Problem von AUTO_INCREMENT
Wert zurücksetzen finden. So werden wir leicht unser Modell wie folgt ändern:

Wir werden in mehreren Schritten vorgehen, um unser Datenmodell zu migrieren. Die DDL-Anweisungen in den folgenden Migrationsskripten wurden unter Verwendung der IDE generiert.
- Zuerst erstellen wir eine neue item_keys Tabelle, die die
AUTO_INCREMENT
Feld halten wird:
-- 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);
- Aber bevor das
AUTO_INCREMENT
Attribut aktivieren, müssen wir bestehende ids in unsere neue Tabelle einfügen:
-- 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
;
- Wir aktivieren jetzt die
AUTO_INCREMENT
Attribut und seinen Wert für zukünftige Einsätze initialisieren:
-- 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;
- Dann können wir die
item1
und item2
Tabellen ändern, um die Primärschlüssel durch einen eindeutigen Index zu ersetzen und Referenz der Primärschlüssel der Tabelle 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)
;
Schließlich
- , wir müssen nur die Trigger erstellen, die die IDs Schöpfung für uns gelingen wird:
-- 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;
|;
Jetzt können wir Daten von einem Tisch zum anderen bewegen, halten die ids unverändert, und wenn wir den Server neu starten, bleibt der Wert AUTO_INCREMENT
in item_keys
gleich.
--------------
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 ist keine Version, es ist eine ganze Familie von Versionen. Bitte geben Sie alle drei Ziffern der Version an. Wenn Sie nicht wissen, zeigen Sie Variablen wie '% version%' ' – derobert
Auch * Ich muss Auto Inkrement Werte anpassen ... beim Start der Anwendung * scheint mir als * Sie tun es falsch *. – derobert
Warum in jedem Forum gibt es einen Typen, der genau weiß, dass ich es falsch mache ??? :) –