我正在制作一个触发器,虽然我很容易并且应该可以正常工作但是它无效。
这是(抽象)表结构:
PK_id | FK1_id | FK2_id | status
1 | 12 | 15 | 'ok'
status
列定义为enum('ok', 'ok_2', 'not_ok') NUT NULL
,没有默认值。
触发器应验证两个FKx_id
值的组合是否已存在,如果是,则应将status
设置为'ok_2',否则设为'ok',如果status
已设置在INSERT INTO
未触及的位置。
我现在拥有的触发器(只有身体!):
BEGIN
DECLARE cnt INT;
SET cnt = (SELECT COUNT(*) FROM `table` WHERE `FK1_id` = NEW.FK1_id AND `FK2_id` = NEW.FK2_id);
IF cnt > 0 AND NEW.status IS NULL THEN
SET NEW.status = 'ok_2';
ELSEIF NEW.status IS NULL THEN
SET NEW.status = 'ok';
END IF;
END
不幸的是,此触发器始终将status
设置为'ok'
- 请注意status
不属于INSERT
查询(因此被视为NULL
)。我之前尝试过这个触发器主体的结果相同:
BEGIN
IF (SELECT COUNT(*) FROM `table` WHERE `FK1_id` = NEW.FK1_id AND `FK2_id` = NEW.FK2_id) > 0 AND NEW.status IS NULL THEN
SET NEW.status = 'ok_2';
ELSEIF NEW.status IS NULL THEN
SET NEW.status = 'ok';
END IF;
END
以及这个(结果完全相同):
BEGIN
IF EXISTS(SELECT * FROM `table` WHERE `FK1_id` = NEW.FK1_id AND `FK2_id` = NEW.FK2_id LIMIT 1) AND NEW.status IS NULL THEN
SET NEW.status = 'ok_2';
ELSEIF NEW.status IS NULL THEN
SET NEW.status = 'ok';
END IF;
END
任何人都可以告诉我为什么即使我插入表中已存在的相同FKx_id
组合,也永远不会遇到第一个条件?
编辑:我切换了条件,结果也一样 - 没有'ok_2'状态设置:
BEGIN
DECLARE cnt INT;
SET cnt = (SELECT COUNT(*) FROM `table` WHERE `FK1_id` = NEW.FK1_id AND `FK2_id` = NEW.FK2_id);
IF cnt = 0 AND NEW.status IS NULL THEN
SET NEW.status = 'ok';
ELSEIF NEW.status IS NULL THEN
SET NEW.status = 'ok_2';
END IF;
END
答案 0 :(得分:1)
知道了。
问题在于status
列的声明:
status enum('ok', 'ok_2', 'not_ok') NOT NULL
如果status
语句中未设置status
,则导致INSERT
预填充第一个枚举值。所以解决方案是下一个触发器体:
BEGIN
DECLARE cnt INT;
SET cnt = (SELECT COUNT(*) FROM `table` WHERE `FK1_id` = NEW.FK1_id AND `FK2_id` = NEW.FK2_id);
IF cnt = 0 THEN
SET NEW.status = 'ok';
ELSEIF NEW.status = 'ok' THEN
SET NEW.status = 'ok_2';
END IF;
END
现在如果我第一次插入
INSERT INTO表(FK_1,FK_2)VALUES(100,150)
状态为'ok'
,如果我第二次插入
INSERT INTO表(FK_1,FK_2)VALUES(100,150)
状态为'ok_2'
,如果我明确设置状态:
INSERT INTO表(FK_1,FK_2,状态)VALUES(100,150,'not_ok')
状态为'not_ok'
。
所以,当使用没有默认值但设置为NOT NULL
的枚举时 - 在省略时不要指望它们在插入时为NULL。可能会预先填充第一个枚举值。