我正在准备一场关于模型驱动开发的考试。我遇到了一个特定的数据库触发器:
CREATE TRIGGER tManager_bi
FOR Manager BEFORE INSERT AS
DECLARE VARIABLE v_company_name CHAR(30);
BEGIN
SELECT M.company
FROM Manager M
WHERE M.nr = NEW.reports_to
INTO :v_company_name;
IF (NOT(NEW.company = v_company_name))
THEN EXCEPTION eReportsNotOwnCompany;
END
此触发器旨在防止经理向外部经理(即不是来自同一家公司的经理)报告的输入。对应的 OCL 约束为:
context Manager
inv: self.company = self.reports_to.company
相关表如下(简化):
CREATE TABLE Manager
(
nr INTEGER NOT NULL,
company VARCHAR(50) NOT NULL,
reports_to INTEGER,
PRIMARY KEY (nr),
FOREIGN KEY (reports_to) REFERENCES Manager (nr)
);
教科书上说,当新插入的管理器不向任何人报告时(即
NEW.reports_to
是 NULL
),这个触发器也能正常工作,实际上,经过测试,它确实能正常工作。但我不明白这一点。如果
NEW.reports_to
是 NULL
,这意味着变量 v_company_name
将为空(未初始化?NULL
?),这意味着比较 NEW.company = v_company_name
将返回 false
,导致抛出异常,对吧?我在这里缺少什么?
(显示的 SQL 应该是 SQL:2003 兼容的。MDD 工具是 Cathedron,它使用 Firebird 作为 RDBMS。)
最佳答案
您忽略了这样一个事实,即当您将 NULL
与 NULL
(或任何其他值)进行比较时,答案是 NULL
,而不是 false
。并且 NULL
的否定仍然是 NULL
,所以在 IF
语句中 ELSE
部分会被触发(如果有的话)。
我建议你阅读 Firebird Null Guide 以更好地理解这一切。
关于sql - 数据库触发器 : comparison of column value with empty variable,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/39056529/