Oracle 触发器创建自动编号

Posted

技术标签:

【中文标题】Oracle 触发器创建自动编号【英文标题】:Oracle trigger to create an autonumber 【发布时间】:2012-01-09 22:42:43 【问题描述】:

我之前从未在 Oracle 中创建过触发器,所以我正在寻找方向。

我想创建一个触发器,如果​​ ID 不在插入语句中,则将 ID 加一。

ID 应该从 10000 开始,当插入一条记录时,下一个 ID 应该是 10001。如果插入语句包含一个 ID,它应该覆盖自动增量。

insert into t1 (firstname, lastname) values ('Michael','Jordan'),('Larry','Bird')

应该看起来像:

名字姓氏ID

迈克尔·乔丹 10000

拉里伯德 10001

insert into t1 (firstname, lastname, id) values ('Scottie','Pippen',50000)

应该看起来像:

名字姓氏ID

迈克尔·乔丹 10000

拉里伯德 10001

斯科蒂·皮蓬 50000

【问题讨论】:

【参考方案1】:

我建议使用触发器本身的条件编写此触发器,而不是在 sql 块中。

CREATE OR REPLACE TRIGGER your_trigger
BEFORE INSERT ON your_table
REFERENCING NEW AS NEW OLD AS OLD
FOR EACH ROW
WHEN (new.id IS NULL)
  BEGIN
    SELECT your_sequence.nextval
    INTO :new.id
    FROM dual;
  END;
/

使用此解决方案,仅当条件匹配(id 为空)时才会执行触发器。

否则触发器总是被执行并且块检查 id 是否为空。 DB 必须执行对非空值不执行任何操作的 SQL 块。

【讨论】:

【参考方案2】:

这样的东西可以在 11g 上运行

CREATE SEQUENCE t1_id_seq 
  start with 10000 
  increment by 1;

CREATE TRIGGER trigger_name
  BEFORE INSERT ON t1
  FOR EACH ROW
DECLARE
BEGIN
  IF( :new.id IS NULL )
  THEN
    :new.id := t1_id_seq.nextval;
  END IF;
END;

如果您使用的是早期版本,则需要执行 SELECT INTO 以从序列中获取下一个值

CREATE TRIGGER trigger_name
  BEFORE INSERT ON t1
  FOR EACH ROW
DECLARE
BEGIN
  IF( :new.id IS NULL )
  THEN
    SELECT t1_id_seq.nextval
      INTO :new.id
      FROM dual;
  END IF;
END;

请注意,Oracle 序列不是无间隙的。因此,出于各种原因,完全有可能跳过特定的值。如果在几分钟、几小时或几天后完成,您的第一个插入的 ID 可能为 10000,第二个插入的 ID 可能为 10020。

另外,请注意,Oracle 不支持在 VALUES 子句中指定多行,就像 mysql 那样。所以而不是

insert into t1 (firstname, lastname) values ('Michael','Jordan'),('Larry','Bird')

你需要两个单独的 INSERT 语句

insert into t1 (firstname, lastname) values ('Michael','Jordan');
insert into t1 (firstname, lastname) values ('Larry','Bird');

【讨论】:

https://github.com/miklagard/oracle-table-creator

以上是关于Oracle 触发器创建自动编号的主要内容,如果未能解决你的问题,请参考以下文章

使用 MySQL 8.0 触发器自动生成内部产品编号

oracle序列怎么用

Oracle里面想实现自动插入递增的序号

Oracle 触发器触发器应用场景--数据的备份和同步

使用 Oracle 创建触发器的问题

Oracle之触发器