sql - 数据库触发器 : comparison of column value with empty variable

标签 sql triggers firebird 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 

此触发器旨在防止经理向外部经理报告的输入,即来自不同公司的经理。对应的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_toNULL),事实上,经过测试,它确实可以正常工作。

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

我在这里错过了什么?

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

最佳答案

您错过了这样一个事实,即当您将 NULLNULL(或任何其他值)进行比较时,答案是 NULL,不是 falseNULL 的否定仍然是 NULL,所以在 IF 语句中 ELSE 部分会触发(如果有一)。

我建议你阅读 Firebird Null Guide为了更好地理解这一切。

关于sql - 数据库触发器 : comparison of column value with empty variable,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39056529/

相关文章:

SQL Server - 选择括号()之间的整数

php - 从选择中获取字符串的某些部分

sql - 约束是在自定义触发器之前还是之后执行的?

sql - 在 postgresql 中将组合插入到表中的更快方法

php - 如何在 Laravel 的单个查询中从多个表中选择多个列?

mysql - mysql中触发工作问题

mysql - 从 Mysql 中选择一种方法而不是另一种方法来获取数据的复杂性

firebird - 将列从 INTEGER 更改为 BIGINT

firebird - Firebird 是否需要手动重新索引?

Delphi XE2 64 位客户端连接到 Firebird 2.5