Le déclencheur MySQL pour mettre à jour un champ à la valeur de id
Question
Je voudrais avoir un déclencheur pour effectuer l'opération suivante pour les enregistrements insérés:
# pseudocode
if new.group_id is null
set new.group_id = new.id
else
# don't touch it
end
Plus clairement: disons que j'ai une table à trois colonnes: id
clé primaire, id_groupe
int, valeur
varchar.
Quand j'insère avec id_groupe
comme cela:
INSERT INTO table(value, group_id) VALUES ('a', 10)
j'aimerais avoir:
id | group_id | value
---+----------+------
1 | 10 | a
mais quand j'omets id_groupe
:
INSERT INTO table(value) VALUES ('b')
il devrait être automatiquement défini sur id
de cet enregistrement:
id | group_id | value
---+----------+------
2 | 2 | b
Est-ce possible avec un déclencheur? (Je sais que je peux mettre à jour l'enregistrement après l'insertion, mais le déclencheur serait plus pratique.)
La solution
Je ne connais aucun moyen de faire cela dans une seule déclaration, même en utilisant un déclencheur.
La solution de déclenchement suggérée par @Lucky ressemblerait à ceci dans MySQL:
CREATE TRIGGER MyTrigger BEFORE INSERT ON MyTable
FOR EACH ROW BEGIN
SET NEW.group_id = COALESCE(NEW.group_id, NEW.id);
END
Cependant, il y a un problème. Dans la phase BEFORE INSERT
, la valeur id
générée automatiquement n'a pas encore été générée. Donc, si id_groupe
est nul, sa valeur par défaut est NEW.id
, qui est toujours 0.
Mais si vous modifiez l'activation de ce déclencheur pendant la phase AFTER INSERT
afin que vous ayez accès à la valeur générée de NEW.id
, vous ne pouvez pas modifier la colonne. valeurs.
MySQL ne prend pas en charge les expressions pour le DEFAULT
d'une colonne, vous ne pouvez donc pas déclarer ce comportement dans la définition de la table.
La seule solution consiste à exécuter INSERT
, puis immédiatement à effectuer un UPDATE
pour modifier id_groupe
s'il n'est pas défini.
INSERT INTO MyTable (group_id, value) VALUES (NULL, 'a');
UPDATE MyTable SET group_id = COALESCE(group_id, id) WHERE id = LAST_INSERT_ID();
Autres conseils
Je réponds ici, comme dans la réponse acceptée, Bill Karwin :
Dans la phase BEFORE INSERT, la valeur id générée automatiquement n'a pas été généré pour le moment. Donc, si group_id est null, sa valeur par défaut est NEW.id qui est toujours 0.
J'ai une réponse à vous donner: pour OP (et les visiteurs à venir), voici quelques points: Vous ne pouvez pas mettre à jour la table à partir de laquelle le déclencheur est appelé. Pour cela, vous obtiendrez Erreur 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.pour mettre à jour la nouvelle ligne
Utilisez le déclencheur BEFORE INSERT ON
. Ainsi, vous pourrez mettre à jour tous les champs de la nouvelle ligne, qui peuvent être accessibles via l'opérateur NEW i.e.
set NEW.group_id = NEW.id
2.Obtenez une valeur auto_increment avant d'insérer :
SELECT AUTO_INCREMENT FROM information_schema.TABLES WHERE TABLE_SCHEMA=DATABASE() AND TABLE_NAME='MyTable'
En résumé, le déclencheur SQL de 'd serait comme suit:
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 ;
Cela fonctionne pour moi
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 ;
Je crois que cela fonctionnera pour vous
j'ai deux tables
test_b: a_id, value
test_c: a_id, value
Et voici un déclencheur sur l’insert du test b. Il vérifie si a_id est null et si c'est le cas, il insère 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)
Ce déclencheur doit faire ce que vous avez demandé.
CREATE TRIGGER mytrigger BEFORE INSERT ON mytable
IF new.group_id IS NULL
SET new.group_id = new.id
END IF
END;
Il est copié à partir d'un exemple très similaire dans la documentation MYSQL. page.
Un déclencheur semble exagéré dans cette situation. Appliquez simplement un paramètre par défaut.
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'
)