MySQL 触发器不完全有效
MySQL Trigger not entirely working
我的触发器没有错误地返回。但是当我测试它时,没有返回错误消息并且测试数据存储在 table.. 这不是我想要的。
基本上(这是为了课程作业),我想要一个触发器,当插入 Barcelona 以外的位置时显示错误消息进入 table.
这是我的触发器。正如我所说,没有错误返回,但它不起作用?
DELIMITER $$
CREATE TRIGGER after_location_insert_finance
AFTER INSERT ON Finance
FOR EACH ROW
BEGIN
DECLARE LocationTrigger varchar(255);
DECLARE msg varchar(255);
SELECT Location INTO LocationTrigger
FROM Finance
WHERE Location != "Barcelona";
IF(LocationTrigger != "Barcelona") THEN
SIGNAL SQLSTATE '45000'
SET MESSAGE_TEXT = 'Not a valid location';
END IF;
END$$
如果 LocationTrigger
为空,IF
中的表达式将不会计算为 TRUE。
如果 Boss
中没有满足 WHERE
子句条件的行,LocationTrigger 将为 NULL。
我不明白为什么没有检查插入到 location
列中的值;或者当我们比较 'Barcelona'
.
的字面值时,为什么我们 运行 是 Boss
table 的查询
似乎我们希望在 BEFORE 触发器而不是 AFTER 触发器中进行这种检查。
我们要允许 location
的 NULL 值吗?
如果我们允许为 location
插入的唯一值是 'Barcelona'
,并且如果我们不允许 NULL 值,那么我们不需要搞乱任何查询Boss
table。做个对比...
BEGIN
IF NOT ( NEW.location <=> 'Barcelona' ) THEN
SIGNAL ...
END IF;
END
也许触发器的目标是实施参照完整性约束(我们通常通过声明 FOREIGN KEY 约束来实施,而不是实施过程。)
假设 "valid" 位置由 Boss
table、
中 location
个值的域定义
假设我们不允许 NULL 值,那么:
BEGIN
DECLARE ls_location VARCHAR(255) DEFAULT NULL;
-- check if the value being inserted exists in a lookup table
SELECT b.location INTO ls_location
FROM Boss b
WHERE b.location = NEW.location
LIMIT 1
;
-- if we didn't find a match, ls_location will be NULL
IF ls_location IS NULL THEN
SIGNAL ...
END IF;
END
如果在 Boss
中找不到匹配的行,则 ls_location
将为 NULL。
"not equals" 与 NULL 的比较将计算为 NULL,而不是 TRUE 或 FALSE。
布尔逻辑 SQL 是三值... TRUE、FALSE 和 NULL
SELECT 0 = 1 AS c0
, 0 <> 1 AS c1
, 0 = NULL AS c2
, 0 <> NULL AS c3
, NULL = NULL AS c4
, NULL <> NULL AS c5
我的触发器没有错误地返回。但是当我测试它时,没有返回错误消息并且测试数据存储在 table.. 这不是我想要的。
基本上(这是为了课程作业),我想要一个触发器,当插入 Barcelona 以外的位置时显示错误消息进入 table.
这是我的触发器。正如我所说,没有错误返回,但它不起作用?
DELIMITER $$
CREATE TRIGGER after_location_insert_finance
AFTER INSERT ON Finance
FOR EACH ROW
BEGIN
DECLARE LocationTrigger varchar(255);
DECLARE msg varchar(255);
SELECT Location INTO LocationTrigger
FROM Finance
WHERE Location != "Barcelona";
IF(LocationTrigger != "Barcelona") THEN
SIGNAL SQLSTATE '45000'
SET MESSAGE_TEXT = 'Not a valid location';
END IF;
END$$
如果 LocationTrigger
为空,IF
中的表达式将不会计算为 TRUE。
如果 Boss
中没有满足 WHERE
子句条件的行,LocationTrigger 将为 NULL。
我不明白为什么没有检查插入到 location
列中的值;或者当我们比较 'Barcelona'
.
Boss
table 的查询
似乎我们希望在 BEFORE 触发器而不是 AFTER 触发器中进行这种检查。
我们要允许 location
的 NULL 值吗?
如果我们允许为 location
插入的唯一值是 'Barcelona'
,并且如果我们不允许 NULL 值,那么我们不需要搞乱任何查询Boss
table。做个对比...
BEGIN
IF NOT ( NEW.location <=> 'Barcelona' ) THEN
SIGNAL ...
END IF;
END
也许触发器的目标是实施参照完整性约束(我们通常通过声明 FOREIGN KEY 约束来实施,而不是实施过程。)
假设 "valid" 位置由 Boss
table、
location
个值的域定义
假设我们不允许 NULL 值,那么:
BEGIN
DECLARE ls_location VARCHAR(255) DEFAULT NULL;
-- check if the value being inserted exists in a lookup table
SELECT b.location INTO ls_location
FROM Boss b
WHERE b.location = NEW.location
LIMIT 1
;
-- if we didn't find a match, ls_location will be NULL
IF ls_location IS NULL THEN
SIGNAL ...
END IF;
END
如果在 Boss
中找不到匹配的行,则 ls_location
将为 NULL。
"not equals" 与 NULL 的比较将计算为 NULL,而不是 TRUE 或 FALSE。
布尔逻辑 SQL 是三值... TRUE、FALSE 和 NULL
SELECT 0 = 1 AS c0
, 0 <> 1 AS c1
, 0 = NULL AS c2
, 0 <> NULL AS c3
, NULL = NULL AS c4
, NULL <> NULL AS c5