error - unknown column in ''field list'' mysql insert
Activador de MySQL para actualizar un campo al valor de id (6)
Me gustaría tener un activador 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 claramente: digamos que tengo una tabla con tres columnas: clave principal id
, 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'')
se debe establecer automáticamente en el 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 disparador sería mejor).
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 que 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 le pediste.
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 .
Esto funciona para mi
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 ;
Estoy respondiendo aquí, como en la respuesta aceptada Bill Karwin afirma:
En la fase ANTES DE INSERTAR, el valor de ID generado automáticamente no se ha generado todavía. Entonces, si group_id es nulo, por defecto es NEW.id, que siempre es 0.
Tengo una respuesta para ello: para OP (y los visitantes que vendrán), aquí hay algunos puntos: No puede actualizar la tabla desde donde se invoca el activador, 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. Use el disparador BEFORE INSERT ON
, de esta manera puede actualizar todos los campos de la nueva fila, a los que se puede acceder a través de NUEVO operador, 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 d sería 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 ;
No conozco ninguna forma de hacer esto en una sola declaración, incluso usando un disparador.
La solución de activación que sugirió @Lucky 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 de id
generado automáticamente no se ha generado todavía. Entonces, si group_id
es nulo, por defecto es NEW.id
que siempre es 0.
Pero si cambia este disparador para que se dispare durante la fase AFTER INSERT
, de modo que tenga acceso al valor generado de NEW.id
, no puede modificar los valores de columna.
MySQL no admite expresiones para el valor 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
inmediatamente 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();
Un disparador parece una exageración en esta situación. Simplemente aplique 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''
)