Ste*_*ker 3 sql firebird triggers model-driven-development
我正准备参加模型驱动开发考试.我遇到了一个特定的数据库触发器:
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
Run Code Online (Sandbox Code Playgroud)
此触发器旨在防止经理向外部经理报告的输入,即不是来自同一公司的经理.相应的OCL约束是:
context Manager
inv: self.company = self.reports_to.company
Run Code Online (Sandbox Code Playgroud)
相关表格看起来像(简化):
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)
);
Run Code Online (Sandbox Code Playgroud)
教科书说当新插入的管理器没有向任何人报告时(即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指南,以便更好地理解它.