【问题标题】:advantage of using a trigger to populate surrogate key in oracle plsql在 oracle plsql 中使用触发器填充代理键的优势
【发布时间】:2013-07-26 15:42:31
【问题描述】:

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

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)

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

【问题讨论】:

  • 您还可以省略序列并在常规表中跟踪分配的 ID。当您拥有可以节省工作并防止人为错误的功能时,您只需使用它;-)
  • 人们可能还想知道为什么当正文忽略更新时它是一个INSERT OR UPDATE 触发器。
  • 在实践中,您可能有更多的列 - 这对于在 INSERT/ 中省略这一列的情况会很好
  • 至于问题,我认为主要是不必调试在插入时意外使用错误序列的问题。去过那里:-/
  • Re: NOT NULL 和 UNIQUE - 这些是对列的很好的约束,但它们不会填充它,这就是这里的重点。此外,如果您在触发器中执行此操作,您不必一直调试程序员忘记添加“sequence.NEXT_VAL”调用,或使用错误序列,或找到键列的最大值和加 1,或者编码人员将设法弄错的所有其他方式。这是拥有幸福生活的秘诀 - 一次完成,一次触发,然后完成。分享和享受。

标签: oracle plsql


【解决方案1】:

这种特定模式实际上非常危险,因为它允许某人手动输入一个新 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 开始,您可以使用identity column,它明确了表和自动增量之间的链接;不需要触发器或序列。表创建 DDL 的语法是:

create table <table_name> ( <column_name> generated as identity );

【讨论】:

  • 我倾向于不同意。插入触发器总是设置 PK 而不检查用户是否提供了合理的默认值,这使得数据库实例之间的数据同步变得更加困难。当然,您可以禁用触发器,执行插入操作,然后再次启用它,但这通常会导致之后有人忘记启用触发器。
  • 但是如果 PK 是序列生成的,则没有合理的默认值可以保证不会与序列值 @Frank 发生冲突。您正在设置自己在将来有一些随机语句失败。
  • 谢谢本。这说得通。我不明白为什么他们决定添加 NVL() 。显然,可以插入大于序列当前值的非冲突键。
  • @Ben 你是对的。但是,如果我将序列值也更新为 max(pk) + 1,我就会再次安全。
【解决方案2】:

触发器和插入语句都有不同的功能主义者 如果您只想插入数据并且不为该插入添加任何日志,那么这个 insert 语句就可以了,但是您可以确保表中数据的完整性,因为另一方面,如果无论您的块触发器中的调用如何,您都希望在表上触发的每个插入/更新语句的日志都会有所帮助,并且可以在任何时间点检查数据完整性。

【讨论】:

  • 感谢您的回答。该死!!,那是一句话吗??
猜你喜欢
  • 1970-01-01
  • 2017-10-30
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-07-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多