sql-MySQL触发器-将SELECT存储在变量中

我有一个触发器,希望在其中拥有一个变量,该变量保存从SELECT获得的INT,因此可以在两个IF语句中使用它,而不必两次调用SELECT。 如何在MySQL触发器中声明/使用变量?

Kenny Linsky asked 2020-01-13T18:12:41Z
5个解决方案
49 votes

您可以使用LIMIT语法在MySQL触发器中声明局部变量。

这是一个例子:

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

为变量分配值时,必须确保查询仅返回单个值,而不返回一组行或一组列。 例如,如果您的查询在实践中返回单个值,则可以,但是一旦返回多个行,您就会得到“ LIMIT”。

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

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//
Bill Karwin answered 2020-01-13T18:13:13Z
7 votes
`CREATE TRIGGER `category_before_ins_tr` BEFORE INSERT ON `category`
  FOR EACH ROW
BEGIN
    **SET @tableId= (SELECT id FROM dummy LIMIT 1);**

END;`;
IgorS answered 2020-01-13T18:13:28Z
6 votes
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$$

不要尝试这个@ home

outis answered 2020-01-13T18:13:48Z
2 votes

或者,您也可以仅在调用触发器的SQL中包含SELECT语句,以便将其作为触发器行中的列之一传入。 只要您确定它将仅返回一行(因此只有一个值)。 (当然,它一定不能返回与触发器中的逻辑进行交互的值,但是在任何情况下都是如此。)

dkretz answered 2020-01-13T18:14:09Z
1 votes

我发布此解决方案是因为我很难找到需要的东西。 这篇文章使我足够接近(谢谢+1),这是在数据与测试匹配的情况下在插入之前重新排列列数据的最终解决方案。

注意:这来自我继承的旧项目,其中:

  1. 唯一密钥是on duplicate key + rrid的组合
  2. 在我接管之前,没有限制来防止重复的唯一键
  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
WEBjuju answered 2020-01-13T18:14:56Z
translate from https://stackoverflow.com:/questions/324605/mysql-trigger-storing-a-select-in-a-variable