数据库触发器:列值与空变量的比较

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_toNULL),这个触发器也能正常工作,实际上,在测试时,它确实可以正常工作.

但我不明白这一点.如果NEW.reports_toNULL,那就意味着变量v_company_name将为空(未初始化??NULL),这意味着比较NEW.company = v_company_name将返回false,导致异常被抛出,对吧?

我在这里错过了什么?

(显示的SQL应该符合SQL:2003标准.MDD工具是Cathedron,它使用Firebird作为RDBMS.)

ain*_*ain 6

你错过了一个事实,当你比较NULLNULL(或任何其他值),答案是NULL,没有false.否定NULL仍然是NULL,所以在IF声明中该ELSE部分将被触发(如果有的话).

我建议你阅读Firebird Null指南,以便更好地理解它.