J'ai un déclencheur dans lequel je veux avoir une variable qui contient un INT que je reçois d'une SELECT
, je peux donc l'utiliser dans deux instructions IF au lieu d'appeler deux fois la SELECT
Comment déclarez-vous/utilisez-vous les variables dans les déclencheurs MySQL?
Vous pouvez déclarer des variables locales dans les déclencheurs MySQL, avec la syntaxe DECLARE
.
Voici un exemple:
DROP TABLE IF EXISTS foo;
CREATE TABLE FOO (
i SERIAL PRIMARY KEY
);
DELIMITER //
DROP TRIGGER IF EXISTS bar //
CREATE TRIGGER bar AFTER INSERT ON foo
FOR EACH ROW BEGIN
DECLARE x INT;
SET x = NEW.i;
SET @a = x; -- set user variable outside trigger
END//
DELIMITER ;
SET @a = 0;
SELECT @a; -- returns 0
INSERT INTO foo () VALUES ();
SELECT @a; -- returns 1, the value it got during the trigger
Lorsque vous affectez une valeur à une variable, vous devez vous assurer que la requête ne renvoie qu'une seule valeur, et non un ensemble de lignes ou un ensemble de colonnes. Par exemple, si votre requête renvoie une valeur unique dans la pratique, c'est correct, mais dès qu'elle renvoie plusieurs lignes, vous obtenez "ERROR 1242: Subquery returns more than 1 row
".
Vous pouvez utiliser LIMIT
ou MAX()
pour vous assurer que la variable locale est définie sur une valeur unique.
CREATE TRIGGER bar AFTER INSERT ON foo
FOR EACH ROW BEGIN
DECLARE x INT;
SET x = (SELECT age FROM users WHERE name = 'Bill');
-- ERROR 1242 if more than one row with 'Bill'
END//
CREATE TRIGGER bar AFTER INSERT ON foo
FOR EACH ROW BEGIN
DECLARE x INT;
SET x = (SELECT MAX(age) FROM users WHERE name = 'Bill');
-- OK even when more than one row with 'Bill'
END//
`CREATE TRIGGER `category_before_ins_tr` BEFORE INSERT ON `category`
FOR EACH ROW
BEGIN
**SET @tableId= (SELECT id FROM dummy LIMIT 1);**
END;`;
CREATE TRIGGER clearcamcdr AFTER INSERT ON `asteriskcdrdb`.`cdr`
FOR EACH ROW
BEGIN
SET @INC = (SELECT sip_inc FROM trunks LIMIT 1);
IF NEW.billsec >1 AND NEW.channel LIKE @INC
AND NEW.dstchannel NOT LIKE ""
THEN
insert into `asteriskcdrdb`.`filtre` (id_appel,date_appel,source,destinataire,duree,sens,commentaire,suivi)
values (NEW.id,NEW.calldate,NEW.src,NEW.dstchannel,NEW.billsec,"entrant","","");
END IF;
END$$
Ne pas essayer ceci @ la maison
Ou vous pouvez simplement inclure l’instruction SELECT dans le SQL qui appelle le déclencheur, afin qu’elle soit transmise comme l’une des colonnes de la ou des lignes du déclencheur. Tant que vous êtes certain qu'il ne renverra infailliblement qu'une seule ligne (donc une valeur). (Et, bien sûr, il ne doit pas renvoyer une valeur qui interagit avec la logique dans le déclencheur, mais c'est vrai dans tous les cas.)
Je poste cette solution parce que j'ai eu du mal à trouver ce dont j'avais besoin. Ce message m’a suffisamment rapproché (+1 pour ce merci), et voici la solution finale pour réorganiser les données de la colonne avant insertion si les données correspondent à un test .
Remarque: ceci provient d'un projet legacy dont j'ai hérité où:
rridprefix
+ rrid
on duplicate key
est moins qu'idéal car les colonnes sont trop nombreuses et peuvent changerQuoi qu'il en soit, voici le déclencheur qui place les clés en double dans une colonne héritée tout en nous permettant de stocker les données héritées et incorrectes (et non de déclencher la clé composite de tables gagnantes, unique) .
BEGIN
-- prevent duplicate composite keys when merging in archive to main
SET @EXIST_COMPOSITE_KEY = (SELECT count(*) FROM patientrecords where rridprefix = NEW.rridprefix and rrid = NEW.rrid);
-- if the composite key to be introduced during merge exists, rearrange the data for insert
IF @EXIST_COMPOSITE_KEY > 0
THEN
-- set the incoming column data this way (if composite key exists)
-- the legacy duplicate rrid field will help us keep the bad data
SET NEW.legacyduperrid = NEW.rrid;
-- allow the following block to set the new rrid appropriately
SET NEW.rrid = null;
END IF;
-- legacy code tried set the rrid (race condition), now the db does it
SET NEW.rrid = (
SELECT if(NEW.rrid is null and NEW.legacyduperrid is null, IFNULL(MAX(rrid), 0) + 1, NEW.rrid)
FROM patientrecords
WHERE rridprefix = NEW.rridprefix
);
END