MySQL dispara para actualizar un campo al valor de id

Me gustaría tener un disparador para realizar la siguiente operación para los registros insertados:

# pseudocode if new.group_id is null set new.group_id = new.id else # don't touch it end 

Más claro: supongamos que tengo una tabla con tres columnas: id clave principal, group_id int, value varchar.

Cuando inserto con group_id así:

 INSERT INTO table(value, group_id) VALUES ('a', 10) 

Me gustaría tener:

 id | group_id | value ---+----------+------ 1 | 10 | a 

pero cuando group_id :

 INSERT INTO table(value) VALUES ('b') 

debe establecerse automáticamente en la id de este registro:

 id | group_id | value ---+----------+------ 2 | 2 | b 

¿Es posible con un gatillo? (Sé que puedo actualizar el registro después de insertarlo, pero tener el activador sería más agradable).

No sé de ninguna manera de hacer esto en una statement, incluso usando un disparador.

La solución de activación que @Lucky sugirió se vería así en MySQL:

 CREATE TRIGGER MyTrigger BEFORE INSERT ON MyTable FOR EACH ROW BEGIN SET NEW.group_id = COALESCE(NEW.group_id, NEW.id); END 

Sin embargo, hay un problema. En la fase BEFORE INSERT , el valor del id generado automáticamente aún no se ha generado. Entonces, si group_id es nulo, su valor predeterminado es NEW.id que siempre es 0.

Pero si cambia este disparador para disparar durante la fase AFTER INSERT , para que tenga acceso al valor generado de NEW.id , no puede modificar los valores de columna.

MySQL no admite expresiones para el DEFAULT de una columna, por lo que tampoco puede declarar este comportamiento en la definición de la tabla.

La única solución es hacer el INSERT , y luego hacer una UPDATE para cambiar el group_id si no está configurado.

 INSERT INTO MyTable (group_id, value) VALUES (NULL, 'a'); UPDATE MyTable SET group_id = COALESCE(group_id, id) WHERE id = LAST_INSERT_ID(); 

Estoy respondiendo aquí, como en la respuesta aceptada Bill Karwin afirma:

En la fase ANTES DE INSERTAR, el valor del ID generado automáticamente aún no se ha generado. Entonces, si group_id es nulo, su valor predeterminado es NEW.id, que siempre es 0.


Tengo una respuesta para eso: para OP (y los visitantes que vendrán), aquí hay algunos puntos: No puede actualizar la tabla desde donde se invoca el desencadenante, para ello obtendrá el Error 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.para actualizar la nueva fila Utilice BEFORE INSERT ON activar BEFORE INSERT ON , de esta manera puede actualizar todos los campos para la nueva fila, a la que se puede acceder a través de un operador NUEVO, es decir,

 set NEW.group_id = NEW.id 

2. Obtenga el valor auto_increment antes de insertar :

 SELECT AUTO_INCREMENT FROM information_schema.TABLES WHERE TABLE_SCHEMA=DATABASE() AND TABLE_NAME='MyTable' 

En resumen: el SQL de activación para algo como lo siguiente:

 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 ; 

Creo que esto funcionará para ti

Tengo dos mesas

 test_b: a_id, value test_c: a_id, value 

Y aquí hay un disparador en el inserto de la prueba b. Comprueba si a_id es nulo y si es inserta 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) 

Este disparador debe hacer lo que usted pidió.

  CREATE TRIGGER mytrigger BEFORE INSERT ON mytable IF new.group_id IS NULL SET new.group_id = new.id END IF END; 

Se copia de un ejemplo muy similar en la página de documentación de MYSQL .

Un desencadenante parece excesivo en esta situación. Simplemente aplica un valor predeterminado.

 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' ) 
    Intereting Posts