Trigger MySQL per aggiornare un campo al valore di id
Domanda
Vorrei avere un trigger per eseguire le seguenti operazioni per i record inseriti:
# pseudocode
if new.group_id is null
set new.group_id = new.id
else
# don't touch it
end
Più chiaramente: dire che ho una tabella con tre colonne: id
chiave primaria, group_id
int, value
varchar.
Quando inserisco con group_id
in questo modo:
INSERT INTO table(value, group_id) VALUES ('a', 10)
Mi piacerebbe avere:
id | group_id | value
---+----------+------
1 | 10 | a
ma quando ometto group_id
:
INSERT INTO table(value) VALUES ('b')
dovrebbe essere automaticamente impostato su id
di questo record:
id | group_id | value
---+----------+------
2 | 2 | b
È possibile con un trigger? (So ??di poter aggiornare il record dopo averlo inserito ma avere il trigger sarebbe più bello.)
Soluzione
Non conosco alcun modo per farlo in una sola istruzione, anche usando un trigger.
La soluzione trigger suggerita da @Lucky sarebbe simile a questa in MySQL:
CREATE TRIGGER MyTrigger BEFORE INSERT ON MyTable
FOR EACH ROW BEGIN
SET NEW.group_id = COALESCE(NEW.group_id, NEW.id);
END
Tuttavia, c'è un problema. Nella fase PRIMA DELL'INSERIMENTO
, il valore id
generato automaticamente non è stato ancora generato. Quindi se group_id
è null, il valore predefinito è NEW.id
che è sempre 0.
Ma se cambi questo trigger in modo che si attivi durante la fase AFTER INSERT
, quindi hai accesso al valore generato di NEW.id
, non puoi modificare la colonna valori.
MySQL non supporta le espressioni per il DEFAULT
di una colonna, quindi non puoi nemmeno dichiarare questo comportamento nella definizione della tabella.
L'unica soluzione è fare il INSERT
, quindi fare immediatamente un UPDATE
per cambiare il group_id
se non è impostato.
INSERT INTO MyTable (group_id, value) VALUES (NULL, 'a');
UPDATE MyTable SET group_id = COALESCE(group_id, id) WHERE id = LAST_INSERT_ID();
Altri suggerimenti
Sto rispondendo qui, come nella risposta accettata Bill Karwin afferma:
Nella fase PRIMA DELL'INSERIMENTO, il valore ID generato automaticamente non è stato generato ancora. Quindi, se group_id è null, il valore predefinito è NEW.id che è sempre 0.
Ho una risposta per questo - per OP (e per i visitatori a venire), ecco alcuni punti: Non è possibile aggiornare la tabella da cui viene richiamato il trigger, poiché verrà visualizzato Errore 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.per aggiornare la nuova riga
Utilizzare il trigger PRIMA DI INSERIRE
, in questo modo è possibile aggiornare tutti i campi per la nuova riga, accessibili tramite NUOVO operatore, ad es.
set NEW.group_id = NEW.id
2. Ottieni il valore di incremento automatico prima di inserire :
SELECT AUTO_INCREMENT FROM information_schema.TABLES WHERE TABLE_SCHEMA=DATABASE() AND TABLE_NAME='MyTable'
Per riassumere: il trigger SQL per "dovrebbe essere qualcosa come il seguente:
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 ;
Questo funziona per me
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 ;
Credo che questo funzionerà per te
Ho due tabelle
test_b: a_id, value
test_c: a_id, value
Ed ecco un trigger sull'inserimento del test b. Verifica se a_id è null e se lo è inserisce 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)
Questo trigger dovrebbe fare quello che hai chiesto.
CREATE TRIGGER mytrigger BEFORE INSERT ON mytable
IF new.group_id IS NULL
SET new.group_id = new.id
END IF
END;
Viene copiato da un esempio molto simile nella documentazione MYSQL pagina
Un trigger sembra eccessivo in questa situazione. Basta applicare un valore predefinito.
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'
)