2

我正在开发一个代码库,它具有以下类型的模式,用于为表生成代理键。

create or replace
TRIGGER TEST_TRIG
BEFORE INSERT  OR UPDATE
ON my_table
REFERENCING NEW AS NEW OLD AS OLD
FOR EACH ROW
DECLARE
BEGIN
   IF INSERTING THEN
      IF NVL(:NEW.column1, 0) = 0 THEN
         SELECT my_table_seq.NEXTVAL
         INTO  :NEW.column1
         FROM  dual;

      END IF;
   END IF;
END;

以及调用此代码的 PL/SQL 逻辑,

begin
     insert into my_table(0);
end;

我的问题是触发器需要什么?为什么不做一个,

insert into my_table(my_table_seq.next_val)

并收工?任何见解将不胜感激。谢谢。

4

2 回答 2

3

这种特殊模式实际上非常危险,因为它允许某人手动输入一个新 ID,该 ID 可能与已经存在的代理键或您的序列将来可能生成的代理键发生冲突。

您的触发器应该看起来像这样,以确保每条新记录都有一个唯一的键。如果您使用的是 11.2 或更高版本,则无需select ... into ...

CREATE OR REPLACE TRIGGER TEST_TRIG
BEFORE INSERT ON my_table
FOR EACH ROW
BEGIN
   :new.column1 := my_table_seq.NEXTVAL;
END;

这种方法的好处是它总是可以完成的。任何人为此列输入的任何值都会被覆盖为可以工作且使用正确顺序的内容;如果有人忘记在语句中添加它仍然有效。

它使您无法破坏您的代理密钥。

根据您的建议,假设有人放置了 1 ;你得到一个主键违规。如果有人忘记了,那么就会有更多的错误。您永远无法保证对表的每次更新都将通过单个入口点进行,因此触发器可以确保正确填充 PK。

值得注意的是,从 12c 开始,您可以使用标识列,它明确了表和自增之间的联系;不需要触发器或序列。表创建 DDL 的语法为:

create table <table_name> ( <column_name> generated as identity );
于 2013-07-26T11:47:14.670 回答
0

如果您只想插入数据并且不为该插入放置日志,那么触发器和插入语句都有不同的功能主义者,那么这个插入语句就可以了,但是您可以确保表中数据的完整性,因为它可以通过修改另一方面,如果您想要在表上触发的每个插入/更新语句的日志,而不管您的块触发器中的调用如何,那么源数量将是有帮助的,并且可以在任何时间点检查数据完整性。

于 2013-07-26T12:09:19.033 回答