【问题标题】:Why is trigger not fired on every single row when using "insert select" or "merge"为什么在使用“插入选择”或“合并”时没有在每一行上触发触发器
【发布时间】:2015-02-02 14:04:41
【问题描述】:

我为一个表定义了一个BEFORE INSERT 触发器,它对于单个INSERTstatements 可以正常工作,但不适用于INSERT ... SELECTMERGE 语句。

这些是我的数据库对象(简化):

CREATE TABLE "COMPANY" (
    "ID" NUMBER NOT NULL,
    "NAME" VARCHAR(100)
);

CREATE TABLE "EMPLOYEE" (
    "ID" NUMBER NOT NULL,
    "COMPANY_ID" NUMBER NOT NULL
);

CREATE UNIQUE INDEX "EMPLOYEE_PK" ON "EMPLOYEE" ("ID");

CREATE SEQUENCE "EMPLOYEE_SEQUENCE";

CREATE TRIGGER "BI_EMPLOYEE" BEFORE INSERT ON "EMPLOYEE" 
    REFERENCING NEW AS newrow FOR EACH ROW BEGIN ATOMIC 
    IF newrow.id IS NULL THEN 
        SET newrow.id = NEXT VALUE FOR employee_sequence;
    END IF;
END;

如果单个 INSERTstatements 被执行,一切都按预期工作,ÌD 是从序列中获取的。但是如果我执行类似

INSERT INTO employee (company_id) SELECT id FROM company;

我得到一个错误:

integrity constraint violation: unique constraint or index violation: "EMPLOYEE_PK"

这可能意味着它尝试从序列中插入相同的键两次。

我正在使用 HSQLDB 的最新版本 2.3.2。

【问题讨论】:

  • 您知道您可以将employee.id 列定义为generated by default as identity,这将完全消除对触发器的需求。
  • @a_horse_with_no_name 是的,但不幸的是我必须反映oracle数据库的结构(这是用于单元测试的)。所以我一定要使用一个序列。
  • 一开始就使用不同的 DBMS 进行单元测试是错误的。这只是 DBMS 之间的许多差异(有时很明显,有时非常微妙)的一个示例。针对不同 DBMS 运行的单元测试并不是真正的有效测试。
  • 但在我看来它确实像一个错误。如果您将其发布到 HSQLDB 讨论组,您可能会得到更好的回应:sourceforge.net/p/hsqldb/discussion/73674(尽管 Fred 也读过 SO)
  • 好的,谢谢。我理解你的意思,但 HSQLDB 及其“Oracle 语法”选项到目前为止做得很好。对 oracle 数据库(而不是嵌入式数据库)进行单元测试真的很困难,尤其是在多个不同的主机(开发人员机器、jenkins 等)上运行测试时。

标签: sql database hsqldb triggers


【解决方案1】:

因为触发器是基于设置的,而不是基于行的。

查看详情here

【讨论】:

  • 这可能适用于 SQL Server,但不适用于 HSQLDB。在 HSQLDB 中(就像在许多其他 DBMS 中一样),您可以在行级触发器和语句级触发器之间进行选择。如果您查看示例,触发器是使用FOR EACH ROW 显式创建的。
  • @Kenan 在 HSQLDB 中有这个 FOR EACH ROW... 所以我认为这是不正确的。
猜你喜欢
  • 1970-01-01
  • 2012-06-06
  • 1970-01-01
  • 2013-09-30
  • 2011-03-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多