MySQL触发器 – 在一个variables中存储一个SELECT

我有一个触发器,我想要一个variables,它包含一个从SELECT获得的INT,所以我可以在两个IF语句中使用它,而不是调用SELECT两次。 你如何在MySQL触发器中声明/使用variables?

您可以使用DECLARE语法在MySQL触发器中声明局部variables。

这是一个例子:

 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 

当为variables赋值时,必须确保查询只返回一个值,而不是一组行或一组列。 例如,如果您的查询在实践中返回单个值,那么可以,但只要它返回多行,就会得到“ ERROR 1242: Subquery returns more than 1 row ”。

您可以使用LIMITMAX()来确保局部variables被设置为单个值。

 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$$ 

不要尝试这个@家

或者,您可以在调用触发器的SQL中包含SELECT语句,以便将其作为触发器行中的一列传入。 只要你确定它肯定会只返回一行(因此一个值)。 (当然,它不能返回一个与触发器中的逻辑相互作用的值,但无论如何也是如此。)

我正在发布这个解决scheme,因为我很难find我需要的东西。 这个post让我足够接近(+1表示感谢),这里是最后的解决scheme重新排列之前插入数据如果数据匹配testing

注意:这是来自我inheritance的遗留项目 ,其中:

  1. Unique Key是rridprefix + rrid的组合
  2. 在我接pipe之前,没有限制重复的唯一密钥
  3. 我们需要将两个表(一个完整的重复)合并到现在对复合键有约束的主表中(所以合并失败,因为获得的表不允许来自不洁表的副本)
  4. on duplicate key是不太理想的,因为列太多,可能会改变

无论如何,这是触发器,将任何重复的键放入遗留列,同时允许我们存储遗留的错误数据(并且不触发获得表复合,唯一键)

 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