如何在trigger中使用case when和update?(代码中有错误)

dldeef67  于 2021-06-25  发布在  Mysql
关注(0)|答案(2)|浏览(293)

我试图创建以下触发器,但我有一个错误。我可以在触发器中使用update或case-when吗?请帮我解决这个问题。
代码说明:我想在插入或更新后更新现有行。如果我没有向“fusdate1”或“fusdate2”添加任何内容,请不要更改“fusdate1”或“fusdate2”
将fusdate更新为新的fusdate,如果我将数据更新或插入到fusdate,则更新插入的fusdate
代码:

delimiter //

create trigger SafetyCertificationTRG
after insert on SafetyCertification
for each row
begin
    case when (FUSDate1='' or FUZDate1 is NULL) then (FUZDate1=OLD.FUSDate1)  else (update SafetyCertification set FUZDate1=NEW.FUSDate1) end;
    case when (FUSDate2='' or FUZDate2 is NULL) then (FUZDate2=NEW.FUSDate2) else (update SafetyCertification set FUZDate2=NEW.FUSDate2) end;
end //

delimiter ;

编辑:我将在这里添加一些信息,使问题更清楚。
我有一列作为fus,它只能获取这3个值:('fus1'、'fus2'和'fus3')我还有3列:fusdate1、fusdate2、fusdate3。
我想根据用户选择的fus将当前日期保存到fusdate1、fusdate2或fusdate3(他们在同一张table上)
我使用了提供的答案,并更改为这个,但我不能做上述。
代码:此代码仅适用于fus1和fusdate1

delimiter //

CREATE TRIGGER  SafetyCertification_bu
BEFORE UPDATE ON   SafetyCertification
FOR EACH ROW
BEGIN
   -- detect a change made to a value in col
   IF OLD.FUS <=> NEW.FUS THEN
      -- value of col is not changed, so do nothing
      DO 0;
   ELSE
      -- we detected a new value was assigned to col
      IF OLD.FUS ='%FUS1%' THEN
         -- we can override the new value, keep it the same
         SET NEW.FUSDate1 = CURDATE();
      END IF;
   END IF;
END //

delimiter ;

另一个代码,我希望做我的工作,但仍然有问题,不更新像上面的代码:

delimiter //

CREATE TRIGGER  SafetyCertification_bu
BEFORE INSERT ON   SafetyCertification
FOR EACH ROW
BEGIN
    IF NEW.FUS='%FUS1%' THEN
         SET new.FUSDate1=MD5(CURDATE());
    END IF;

END //

delimiter ;

更新3:
在更新或插入任何数据时,answer中提供的第三个代码不会向fusdate1、2和3添加任何内容。
代码

DELIMITER $$

CREATE TRIGGER  SafetyCertification_bu
BEFORE UPDATE ON   SafetyCertification
FOR EACH ROW
BEGIN
   -- set one of the `fusdateN` columns to current date
   -- which column to set depends on the value assigned to `fus` 
   IF NEW.fus = 'FUS1' THEN
      SET NEW.fusdate1 = DATE(NOW());
   ELSEIF NEW.fus = 'FUS2' THEN
      SET NEW.fusdate2 = DATE(NOW());
   ELSEIF NEW.fus = 'FUS3' THEN
      SET NEW.fusdate3 = DATE(NOW());
   END IF;
END$$

DELIMITER ;
py49o6xq

py49o6xq1#

几个注意事项:
触发器不能对触发触发器的表发出更新,这是禁止的。
不合格的参考文献(如。 FUSDate1 以及 FUZDate1 )无效。那些参考资料不能解决任何问题。
引用 OLD.FUSDate1 在插入后触发器的上下文中无效。在更新触发器中 OLD.col 更新前列的值。
表达式 (FUZDate1=OLD.FUSDate1) 不是赋值,而是将返回0、1或null的比较。
如果我们想触发 UPDATE 和一个 INSERT ,这将需要两个单独的触发器。
如果要修改当前行的内容,可以使用 BEFORE 触发而不是 AFTER .
我想在插入或更新后更新现有行。
在插入或更新行之前应用更改要容易得多。我们可以给一列赋值 col 通过引用 NEW.col 在学校的作业中 BEFORE INSERT 或者 BEFORE UPDATE 触发。例如:

SET NEW.col = expr;

不要改变方向 FUSDate1 或者 FUSDate2 如果我不加任何东西 FUSDate1 或者 FUSDate2 这看起来很简单。只是别给我分配任务 NEW.FUSDate1 或者 NEW.FUSDate2 .
将fusdate更新为新的fusdate,如果我将数据更新或插入到fusdate,则更新插入的fusdate
建议的触发器示例包含对 FUZDate1 或者 FUZDate2 ,但规范中没有提到这些列。说明书很混乱。
UPDATE 语句将为列赋值,而不需要触发器。一 INSERT 语句可以为列赋值,同样,也不需要为此设置触发器。
规格不清楚。提供示例起始状态(表中的行)和示例insert或update语句,以及执行语句后所需的状态,将大大有助于澄清需求。
演示 BEFORE UPDATE 阻止将新值赋给特定列的触发器:

DELIMITER $$

CREATE TRIGGER  SafetyCertification_bu
BEFORE UPDATE ON   SafetyCertification
FOR EACH ROW
BEGIN
   -- detect a change made to a value in col
   IF OLD.col <=> NEW.col THEN
      -- value of col is not changed, so do nothing
      DO 0;
   ELSE
      -- we detected a new value was assigned to col
      IF OLD.col IS NOT NULL THEN
         -- we can override the new value, keep it the same
         SET NEW.col = OLD.col;
      END IF;
   END IF;
END$$

DELIMITER ;

对于这个示例触发器实现的功能,我们不一定需要那么多 IF 条件;这些都是为了演示我们可以执行的一些检查,以及如何引用 col 以及分配给 col .
后续行动
根据问题中的更新信息,下面是一个 BEFORE UPDATE 符合规范的触发器。
这是给 UPDATE 行动。为了得到同样的行为 INSERT 语句,则需要重复此触发器定义 BEFORE INSERT 代替 BEFORE UPDATE .
(我会用这个名字 _bu 对于更新前触发器,以及 _bi 用于插入触发器之前。)

DELIMITER $$

CREATE TRIGGER  SafetyCertification_bu
BEFORE UPDATE ON   SafetyCertification
FOR EACH ROW
BEGIN
   -- set one of the `fusdateN` columns to current date
   -- which column to set depends on the value assigned to `fus` 
   IF NEW.fus = 'FUS1' THEN
      SET NEW.fusdate1 = DATE(NOW());
   ELSEIF NEW.fus = 'FUS2' THEN
      SET NEW.fusdate2 = DATE(NOW());
   ELSEIF NEW.fus = 'FUS3' THEN
      SET NEW.fusdate3 = DATE(NOW());
   END IF;
END$$

DELIMITER ;

第二次随访
回答关于使用 CASE WHEN mysql存储程序上下文中的语句。。。
我们可以实现示例触发器(在这个答案的正上方)来替换 IF-THEM 两种形式的 CASE 声明。
任何一个

CASE 
      WHEN NEW.fus = 'FUS1' THEN
         SET NEW.fusdate1 = DATE(NOW());
      WHEN NEW.fus = 'FUS2' THEN
         SET NEW.fusdate2 = DATE(NOW());
      WHEN NEW.fus = 'FUS3' THEN
         SET NEW.fusdate3 = DATE(NOW());
   END CASE;

-或者-

CASE NEW.fus 
      WHEN 'FUS1' THEN
         SET NEW.fusdate1 = DATE(NOW());
      WHEN 'FUS2' THEN
         SET NEW.fusdate2 = DATE(NOW());
      WHEN 'FUS3' THEN
         SET NEW.fusdate3 = DATE(NOW());
   END CASE;

笔记
这个 CASE 语句在mysql存储程序中可用;在存储程序之外,它不是有效的sql语句。
另外,我们不应该将这个case语句与case表达式混淆。case表达式在sql语句的上下文中有效,例如 SELECT 或者 UPDATE 声明。
示范
“我检查了触发器,但不幸的是没有保存任何内容。”
@克里斯蒂亚诺:这里有一个简单的演示
创建表

CREATE TABLE `safety_certification`
( id INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY
, fus       VARCHAR(5)
, fusdate1  DATE
, fusdate2  DATE
, fusdate3  DATE
) ENGINE=INNODB
;

用演示行填充表

INSERT INTO `safety_certification` (id, fus, fusdate1, fusdate2, fusdate3) VALUES
( 1, '', NULL, NULL, NULL)
,( 2, '', NULL, NULL, NULL)
,( 3, '', NULL, NULL, NULL)
,( 4, '', NULL, NULL, NULL)
,( 5, '', NULL, NULL, NULL)
;

创建触发器

DELIMITER $$

CREATE TRIGGER  `safety_certification_bu`
BEFORE UPDATE ON   `safety_certification`
FOR EACH ROW
BEGIN
   -- set one of the `fusdateN` columns to current date
   -- which column to set depends on the value assigned to `fus`
   IF NEW.fus = 'FUS1' THEN
      SET NEW.fusdate1 = DATE(NOW());
   ELSEIF NEW.fus = 'FUS2' THEN
      SET NEW.fusdate2 = DATE(NOW());
   ELSEIF NEW.fus = 'FUS3' THEN
      SET NEW.fusdate3 = DATE(NOW());
   END IF;
END$$

DELIMITER ;

更新将在我们刚刚定义的更新触发器之前执行

UPDATE `safety_certification` sc SET sc.fus = 'FUS1' WHERE sc.id = 1 ;
UPDATE `safety_certification` sc SET sc.fus = 'FUS2' WHERE sc.id = 2 ;
UPDATE `safety_certification` sc SET sc.fus = 'FUS3' WHERE sc.id = 3 ;
UPDATE `safety_certification` sc SET sc.fus = 'FUS4' WHERE sc.id = 4 ;

显示表格内容

SELECT * FROM `safety_certification`;

退货:

id  fus     fusdate1    fusdate2    fusdate3
------  ------  ----------  ----------  ------------
     1  FUS1    2018-05-04  (NULL)      (NULL)
     2  FUS2    (NULL)      2018-05-04  (NULL)
     3  FUS3    (NULL)      (NULL)      2018-05-04
     4  FUS4    (NULL)      (NULL)      (NULL)
     5          (NULL)      (NULL)      (NULL)

当一些特定的值被分配给fus时,触发器似乎正在按照规范填充fusdate1、fusdate2和fusdate3列

rmbxnbpk

rmbxnbpk2#

我也遇到了同样的问题,我使用了两个触发器,第一个触发器将数据发送到另一个表,所以现在可以创建另一个触发器将数据发送到第一个表。我认为这是低性能,但这是我达到它的唯一途径。我希望其他人有另一个解决方案。

相关问题