Ich habe eine BEFORE INSERT TRIGGER
, die verwendet wird, um den AUTO_INCREMENT
Wert einer Spalte (id_2
) zu berechnen.Ändern der LAST_INSERT_ID() aus einem TRIGGER in MySQL
id_1 | id_2 | data
1 | 1 | 'a'
1 | 2 | 'b'
1 | 3 | 'c'
2 | 1 | 'a'
2 | 2 | 'b'
2 | 3 | 'c'
2 | 4 | 'a'
3 | 1 | 'b'
3 | 2 | 'c'
Ich habe PRIMARY (ID_1, ID_2) und ich bin mit InnoDB. Vorher verwendete die Tabelle MyISAM und ich hatte keine Probleme: id_2
wurde auf AUTO_INCREMENT
festgelegt, so dass jeder neue Eintrag für id_1
neue id_2
allein erzeugen würde. Jetzt, nach InnoDB Schalt, ich habe diesen Trigger, das Gleiche zu tun:
SET @id = NULL;
SELECT COALESCE(MAX(id_2) + 1, 1) INTO @id FROM tbl WHERE id_1 = NEW.id_1;
SET NEW.id_2= @id;
Es funktioniert perfekt, außer jetzt die LAST_INSERT_ID()
falschen Wert hat (es gibt 0) gewonnen. Eine Menge Code hängt davon ab, dass LAST_INSERT_ID()
korrekt ist. Seit MySQL 5.0.12 haben jedoch alle Änderungen, die innerhalb von TRIGGERS an LAST_INSERT_ID
vorgenommen werden, keinen Einfluss auf den globalen Wert. Gibt es eine Möglichkeit, dies zu umgehen? Ich kann leicht den AFTER UPDATE TRIGGER
eingestellt, die die LAST_INSERT_ID
ändert durch LAST_INSERT_ID(NEW.id_2)
Aufruf jedoch jeder Client-Seite würde LAST_INSERT_ID
auf 0 gesetzt
erhalten Gibt es eine Arbeits Behelfslösung MySQL zu zwingen, den Zustand der LAST_INSERT_ID
zu halten, die im Inneren verändert wurde der Auslöser? Gibt es eine andere Alternative, als zurück zu MyISAM zu wechseln, das dieses sofort unterstützt oder ein anderes SELECT max(id_2) FROM tbl WHERE id_1 = :id
als Teil der Transaktion ausführt, um sicherzustellen, dass die gefundene Zeile diejenige ist, die früher eingefügt wurde?
> SHOW CREATE TABLE tbl;
CREATE TABLE `tbl` (
`id_1` int(11) NOT NULL,
`id_2` int(11) NOT NULL,
`data` varchar(255) COLLATE utf8_unicode_ci NOT NULL,
PRIMARY KEY (`id_1`,`id_2`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci
Beispiel:
INSERT INTO tbl (id_1, id_2, data) VALUES (1, NULL, 'd');
SELECT LAST_INSERT_ID();
Die erste Anweisung wird die Zeile 1 | 4 | 'd'
in die Tabelle einfügen. Die zweite Anweisung gibt 0
zurück, aber ich brauche es, um 4
zurückzugeben.
Wie Ravinder Reddy gefragt, die kurze Erklärung über das System und fügte hinzu:
ich eine Tabelle, die Körbe, und ich habe eine andere Tabelle enthält (tbl
), dieElemente enthält. Der Basket wird von der Anwendung erstellt und erhält eine ID von AUTO_INCREMENT
auf Basket-Tabelle. Die Aufgabe besteht darin, Elemente in den Korb mit ID = id_1
in tbl
einzufügen und ihnen eine eindeutige ID innerhalb des Geltungsbereichs dieses Korbs zuzuordnen. Jedes Element hat etwas data
damit verbunden, das innerhalb desselben Korbes wiederholen kann. In der Praxis versuche ich also, alle data
Einträge in einem einzigen Korb zu speichern, und dann in der Lage zu sein, auf diese einzelnen Einträge durch ihre id_1
- id_2
Paare verweisen (und abrufen).
Ich bin ein wenig verwirrt, aber wie hätten Sie eine LAST_INSERT_ID() _before_ die INSERT ausgeführt wird? Ich glaube, LAST_INSERT_ID() ist nur dann zuverlässig, wenn ein Insert auf derselben Client-Verbindung ausgeführt wurde. Wenn die Anwendung eine Verbindung öffnet, eine Einfügung ausführt und dann die Verbindung schließt, können Sie nicht einfach eine neue Verbindung öffnen und auf LAST_INSERT_ID() zugreifen, ohne zuvor eine Einfügung für diese Verbindung ausgeführt zu haben, bevor die Funktion aufgerufen wird. –
Ich machte den Aufruf von 'LAST_INSERT_ID()' nachdem das INSERT abgeschlossen war, also nachdem der Trigger beendet wurde. Mit anderen Worten hatte der Auslöser, um den Wert für die zweite Spalte des zweispaltigen Primärschlüssels zu generieren, keine Möglichkeit, den neu festgelegten Wert zu kommunizieren. Ich habe der Frage ein Beispiel hinzugefügt. – Xeos
@Xeos: Können Sie bitte 'show create table tbl' output zum Beitrag hinzufügen? –