如何在触发器中使用 Case-When 和 Update?(我的代码出错)
How to use Case-When and Update in Trigger?(Error in my code)
我试图在下面创建触发器,但出现错误。
我可以在触发器中使用更新或使用 'case when' 吗?
请帮我解决这里的问题。
代码说明:
我想在插入或更新后更新我现有的行。
不要更改 'FUSDate1' 或 'FUSDate2' 如果我没有向 'FUSDate1' 或 'FUSDate2'
添加任何内容
将 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:
当我更新或插入任何数据时,答案中提供的第三个代码不会向 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 ;
我遇到了同样的问题,我使用了两个触发器,
第一个触发器将数据发送到另一个 table,因此现在您可以创建另一个触发器将此数据发送到第一个 table。我认为这是低性能,但这是我达到它的唯一方法。我希望其他人有其他解决方案。
一些注意事项:
触发器不能针对触发触发器的 table 发出更新,这是被禁止的。
不合格的引用(例如 FUSDate1
和 FUZDate1
)无效。这些引用没有解决任何问题。
对 OLD.FUSDate1
的引用在 AFTER INSERT 触发器的上下文中无效。在 UPDATE 触发器中,OLD.col
指更新前 col 的值。
表达式 (FUZDate1=OLD.FUSDate1)
不是赋值,它是一个比较 return 0、1 或 NULL。
如果我们想在 UPDATE
和 INSERT
上触发,则需要两个单独的触发器。
如果我们要修改当前行的内容,可以使用BEFORE
触发器代替AFTER
。
我想在插入或更新后更新现有行。
在插入或更新行之前应用更改会容易得多。我们可以通过在 BEFORE INSERT
或 BEFORE UPDATE
触发器的赋值中引用 NEW.col
来为列 col
赋值。例如:
SET NEW.col = expr;
不要更改 FUSDate1
或 FUSDate2
如果我没有向 FUSDate1
或 FUSDate2
添加任何内容
这看起来很简单。只是不要对 NEW.FUSDate1
或 NEW.FUSDate2
.
进行任何分配
将FUSDate更新为新的或插入的如果我更新或插入数据到FUSDate
提议的触发器示例包含对 FUZDate1
或 FUZDate2
的引用,但规范中未提及这些列。规范令人困惑。
UPDATE
语句将为列赋值,不需要触发器来执行此操作。 INSERT
语句可以为列赋值,同样,不需要触发器。
规格不明确。提供示例起始状态(table 中的行)和示例 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 ;
第二次跟进
回答有关在 MySQL 存储程序的上下文中使用 CASE WHEN
语句的问题...
我们可以实现示例触发器(在此答案的正上方)用 CASE
语句的两种形式之一替换 IF-THEM
。
任一
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
语句。
演示
"I examined the Trigger, But unfortunately does not save anything in fusDates."
@Christiano:这是一个简单的演示
创建table
CREATE TABLE `safety_certification`
( id INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY
, fus VARCHAR(5)
, fusdate1 DATE
, fusdate2 DATE
, fusdate3 DATE
) ENGINE=INNODB
;
使用演示行table填充
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 ;
显示table
的内容
SELECT * FROM `safety_certification`;
returns:
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 列
我试图在下面创建触发器,但出现错误。 我可以在触发器中使用更新或使用 'case when' 吗? 请帮我解决这里的问题。
代码说明: 我想在插入或更新后更新我现有的行。 不要更改 'FUSDate1' 或 'FUSDate2' 如果我没有向 'FUSDate1' 或 'FUSDate2'
添加任何内容将 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:
当我更新或插入任何数据时,答案中提供的第三个代码不会向 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 ;
我遇到了同样的问题,我使用了两个触发器, 第一个触发器将数据发送到另一个 table,因此现在您可以创建另一个触发器将此数据发送到第一个 table。我认为这是低性能,但这是我达到它的唯一方法。我希望其他人有其他解决方案。
一些注意事项:
触发器不能针对触发触发器的 table 发出更新,这是被禁止的。
不合格的引用(例如 FUSDate1
和 FUZDate1
)无效。这些引用没有解决任何问题。
对 OLD.FUSDate1
的引用在 AFTER INSERT 触发器的上下文中无效。在 UPDATE 触发器中,OLD.col
指更新前 col 的值。
表达式 (FUZDate1=OLD.FUSDate1)
不是赋值,它是一个比较 return 0、1 或 NULL。
如果我们想在 UPDATE
和 INSERT
上触发,则需要两个单独的触发器。
如果我们要修改当前行的内容,可以使用BEFORE
触发器代替AFTER
。
我想在插入或更新后更新现有行。
在插入或更新行之前应用更改会容易得多。我们可以通过在 BEFORE INSERT
或 BEFORE UPDATE
触发器的赋值中引用 NEW.col
来为列 col
赋值。例如:
SET NEW.col = expr;
不要更改 FUSDate1
或 FUSDate2
如果我没有向 FUSDate1
或 FUSDate2
添加任何内容
这看起来很简单。只是不要对 NEW.FUSDate1
或 NEW.FUSDate2
.
将FUSDate更新为新的或插入的如果我更新或插入数据到FUSDate
提议的触发器示例包含对 FUZDate1
或 FUZDate2
的引用,但规范中未提及这些列。规范令人困惑。
UPDATE
语句将为列赋值,不需要触发器来执行此操作。 INSERT
语句可以为列赋值,同样,不需要触发器。
规格不明确。提供示例起始状态(table 中的行)和示例 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 ;
第二次跟进
回答有关在 MySQL 存储程序的上下文中使用 CASE WHEN
语句的问题...
我们可以实现示例触发器(在此答案的正上方)用 CASE
语句的两种形式之一替换 IF-THEM
。
任一
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
语句。
演示
"I examined the Trigger, But unfortunately does not save anything in fusDates."
@Christiano:这是一个简单的演示
创建table
CREATE TABLE `safety_certification`
( id INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY
, fus VARCHAR(5)
, fusdate1 DATE
, fusdate2 DATE
, fusdate3 DATE
) ENGINE=INNODB
;
使用演示行table填充
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 ;
显示table
的内容SELECT * FROM `safety_certification`;
returns:
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 列