MySQL -Auslöser, um ein Feld auf den Wert der ID zu aktualisieren
Frage
Ich möchte einen Auslöser für den folgenden Vorgang für eingefügte Datensätze ausführen:
# pseudocode
if new.group_id is null
set new.group_id = new.id
else
# don't touch it
end
Genauer gesagt: Sagen Sie, ich habe eine Tabelle mit drei Spalten: id
Primärschlüssel, group_id
int, value
varchar.
Wenn ich mit einfüge mit group_id
so wie das:
INSERT INTO table(value, group_id) VALUES ('a', 10)
Ich hätte gerne:
id | group_id | value
---+----------+------
1 | 10 | a
Aber wenn ich weglässt group_id
:
INSERT INTO table(value) VALUES ('b')
Es sollte automatisch auf die festgelegt werden id
dieser Aufzeichnung:
id | group_id | value
---+----------+------
2 | 2 | b
Ist es mit einem Auslöser möglich? (Ich weiß, ich kann den Datensatz nach dem Einfügen aktualisieren, aber der Auslöser wäre schöner.)
Lösung
Ich weiß keine Möglichkeit, dies in einer Aussage zu tun, selbst wenn ich einen Auslöser benutze.
Die Trigger -Lösung, die @Lucky vorgeschlagen hat, würde in MySQL so aussehen:
CREATE TRIGGER MyTrigger BEFORE INSERT ON MyTable
FOR EACH ROW BEGIN
SET NEW.group_id = COALESCE(NEW.group_id, NEW.id);
END
Es gibt jedoch ein Problem. In dem BEFORE INSERT
Phase, die automatisch generierte id
Wert wurde noch nicht generiert. Also wenn group_id
ist NULL, es wird standardmäßig angelegt NEW.id
Welches ist immer 0.
Aber wenn Sie diesen Auslöser in das Feuer während deses ändern AFTER INSERT
Phase, also haben Sie Zugriff auf den generierten Wert von NEW.id
, Sie können die Spaltenwerte nicht ändern.
MySQL unterstützt keine Ausdrücke für die DEFAULT
einer Spalte, so dass Sie dieses Verhalten auch in der Tabellendefinition nicht deklarieren können.
Die einzige Lösung besteht darin, das zu tun INSERT
, und dann sofort eine machen UPDATE
um es zu ändern group_id
Wenn es nicht festgelegt ist.
INSERT INTO MyTable (group_id, value) VALUES (NULL, 'a');
UPDATE MyTable SET group_id = COALESCE(group_id, id) WHERE id = LAST_INSERT_ID();
Andere Tipps
Ich antworte hier, wie in der akzeptierten Antwort Bill Karwin Zustände:
In der Voreinfügungsphase wurde der automatisch generierte ID-Wert noch nicht generiert. Also, wenn Group_id null ist, ist es standardmäßig mit New.id, was immer 0 ist.
Ich habe eine Antwort darauf - für OP (und die zu kommenden Besucher) sind hier nur wenige Punkte: Sie können die Tabelle nicht aktualisieren, wo der Trigger aufgerufen wird, denn sie erhalten Sie Fehler 1442:
Error Code: 1442
Can't update table 'MyTable' in stored function/trigger because it is already used by statement which invoked this stored function/trigger.
1. Um die neue Zeile zu aktualisierenVerwenden BEFORE INSERT ON
Auf diese Weise können Sie alle Felder für die neue Zeile aktualisieren, auf die über einen neuen Bediener -IE zugegriffen werden kann
set NEW.group_id = NEW.id
2.GET AUTO_INCREMENT -Wert vor dem Einfügen:
SELECT AUTO_INCREMENT FROM information_schema.TABLES WHERE TABLE_SCHEMA=DATABASE() AND TABLE_NAME='MyTable'
Zusammenfassend - der Trigger SQL für 'D ist etwas wie folgt:
DELIMITER //
DROP TRIGGER IF EXISTS MyTrigger//
CREATE TRIGGER MyTrigger BEFORE INSERT ON MyTable
FOR EACH ROW BEGIN
IF new.group_id IS NULL
set @auto_id := (SELECT AUTO_INCREMENT FROM INFORMATION_SCHEMA.TABLES
WHERE TABLE_NAME='MyTable' AND TABLE_SCHEMA=DATABASE() );
set NEW.group_id = @auto_id;
ENF IF;
END;
//
DELIMITER ;
Das funktioniert für mich
DELIMITER $$
CREATE TRIGGER `myTriggerNameHere`
BEFORE INSERT ON `table` FOR EACH ROW
BEGIN
SET NEW.group_id = IF(NEW.group_id IS NULL, LAST_INSERT_ID()+1, NEW.group_id);
END;
$$
DELIMITER ;
Ich glaube, dass dies für Sie funktionieren wird
Ich habe zwei Tische
test_b: a_id, value
test_c: a_id, value
Und hier ist ein Auslöser am Einsatz des Tests b. Es prüft, ob a_id null ist und ob es sich um 0 einfügt. 0
CREATE TRIGGER test_b AFTER INSERT ON test_b
FOR EACH ROW
INSERT INTO test_c (a_id, value) VALUES (IFNULL(NEW.a_id, 0),NEW.value)
Dieser Auslöser sollte das tun, was Sie gefragt haben.
CREATE TRIGGER mytrigger BEFORE INSERT ON mytable
IF new.group_id IS NULL
SET new.group_id = new.id
END IF
END;
Es wird von einem sehr ähnlichen Beispiel in der kopiert MySQL -Dokumentation Seite.
Ein Auslöser scheint in dieser Situation übertrieben zu sein. Wenden Sie einfach einen Standard an.
CREATE TABLE `test` (
`id` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT,
`value` varchar(100) NOT NULL,
`group_id` TINYINT(3) UNSIGNED NOT NULL DEFAULT '2'
)