令全球数据库管理员感到沮丧的是,在 2014 年年中 Oracle 版本 12c 之前,Oracle 根本不具备在表模式中固有地生成自动递增列的固有能力。虽然这个设计决定的原因只能猜测,但好消息是,即使对于旧 Oracle 系统上的用户,也有一种可能的解决方法来绕过这个陷阱并创建自己的自动递增主键列。
创建序列
第一步是SEQUENCE在您的数据库中创建一个数据对象,它是一个数据对象,多个用户可以访问以自动生成递增值。正如文档中所讨论的,Oracle 中的序列可以防止同时创建重复值,因为在生成每个序列项之前,多个用户实际上被迫“轮流”。
为了为新表创建唯一主键,首先我们必须CREATE
要使用的表:
CREATE TABLE books (
id NUMBER(10) NOT NULL,
title VARCHAR2(100) NOT NULL
);
接下来我们需要添加一个PRIMARY KEY
约束:
ALTER TABLE books
ADD (
CONSTRAINT books_pk PRIMARY KEY (id)
);
最后,我们将创建我们的SEQUENCE
,稍后将使用它来实际生成唯一的、自动递增的值。
CREATE SEQUENCE books_sequence;
添加触发器
虽然我们已经创建了表并准备就绪,但到目前为止,我们的序列只是坐在那里,但从未投入使用。这就是TRIGGERS进来的地方。
与event
现代编程语言中的 a类似TRIGGER
,Oracle 中的 a 是在特定事件发生时执行的存储过程。
通常 aTRIGGER
将被配置为在更新表或删除记录时触发,在必要时提供一些清理。
在我们的例子中,我们希望在我们的表中执行我们的TRIGGER
先验,确保我们的递增并且新值被传递到我们的主键列。INSERT
books
SEQUENCE
CREATE OR REPLACE TRIGGER books_on_insert
BEFORE INSERT ON books
FOR EACH ROW
BEGIN
SELECT books_sequence.nextval
INTO :new.id
FROM dual;
END;
在这里,我们正在创建(或替换如果存在)TRIGGER
命名books_on_insert
并指定我们希望触发器BEFORE INSERT
为books
表触发,并适用于其中的任何和所有行。
触发器本身的“代码”相当简单:我们SELECT
从之前创建的 中获取下一个增量值books_sequence
SEQUENCE
,并将其插入到表中指定字段的:new
记录中。books
.id
注意:该FROM dual
部分是完成正确查询所必需的,但实际上无关紧要。该dual
表只是单个虚拟数据行,并且在这种情况下被添加,只是为了可以忽略它,我们可以改为执行触发器的系统函数,而不是返回某种类型的数据。
IDENTITY
IDENTITY列是在 Oracle 12c 中引入的,允许在现代版本的 Oracle 中实现简单的自动增量功能。
使用该IDENTITY
列在功能上类似于其他数据库系统。在现代 Oracle 12c 或更高版本中重新创建上books
表模式,我们只需使用以下列定义。
CREATE TABLE books (
id NUMBER GENERATED BY DEFAULT ON NULL AS IDENTITY,
title VARCHAR2(100) NOT NULL
);