Oracle中实现ID自增


一、自增列

自增列是数据库中值随插入的每个行自动增加的一列。它最常用于主键或 ID 字段,这样每次增加一行时,不用指该字段的值,它就会自动增加,而且是唯一的。

当在 MySQL 中定义列时,我们可以指定一个名为 AUTO_INCREMENT 的参数。然后,每当将新值插入此表中时,放入此列的值比最后一个值加 1。

但很不幸,Oracle 没有 AUTO_INCREMENT 功能。 那要如何在Oracle中做到这一点呢?

二、在Oracle11中设置自增字段

Oracle里的序列(SEQUENCE),可间接实现自增主键的作用。
序列(Sequence),又叫序列生成器,用于提供一系列的数字,开发人员使用序列生成唯一键。每次访问序列,序列按照一定的规律增加或者减少。
序列的定义存储在SYSTEM表空间中,序列不像表,它不会占用磁盘空间。
序列独立于事务,每次事务的提交和回滚都不会影响序列。

1.创建序列

CREATE SEQUENCE TEST_ID_SEQ
INCREMENT BY 1
START WITH 1
MINVALUE 1 
MAXVALUE 999999999
NOCYCLE
NOCACHE
ORDER; 

SEQUENCE说明:

  1. INCREMENT BY: 用于指定序列增量(默认值:1),如果指定的是正整数,则序列号自动递增,如果指定的是负数,则自动递减。
  2. START WITH : 用于指定序列生成器生成的第一个序列号,当序列号顺序递增时默认值为序列号的最小值,当序列号顺序递减时默认值为序列号的最大值。
  3. MINVALUE : 用于指定序列生成器可以生成的最小序列号(必须小于或等于 START WITH,并且必须小于 MAXVALUE),默认值为 NOMINVALUE。
  4. MAXVALUE : 用于指定序列生成器可以生成的组大序列号(必须大于或等于 START WITH,并且必须大于 MINVALUE),默认为 NOMAXVALUE。
  5. CYCLE or NOCYCLE : 用于指定在达到序列的最大值或最小值之后是否继续生成序列号,默认为 NOCYCLE。
  6. CACHE or NOCACHE : 用于指定在内存中可以预分配的序列号个数(默认值:20)。
  7. ORDER or NOORDER : 设置是否按照请求的顺序产生序列
    如果需要删除序列,可以使用下面的命令:
    DROP SEQUENCE TEST_ID_SEQ;
    到这一步其实就已经可以实现字段自增,只要插入的时候,将 ID 的值设置为序列的下一个值 TEST_ID_SEQ.NEXTVAL 就可以了:
    先创建测试表:
    CREATE TABLE "TEST" (
     ID NUMBER(11) PRIMARY KEY,
     NAME VARCHAR2(50BYTE) NOT NULL
    );
    插入数据:
    SQL> INSERT INTO "TEST" ("ID", "NAME") VALUES (TEST_ID_SEQ.NEXTVAL, 'name1');
    SQL> INSERT INTO "TEST" ("ID", "NAME") VALUES (TEST_ID_SEQ.NEXTVAL, 'name2');
    SQL> INSERT INTO "TEST" ("ID", "NAME") VALUES (TEST_ID_SEQ.NEXTVAL, 'name3');
    SQL> SELECT * FROM "TEST";
    

ID NAME


100 name1
101 name2
102 name3

为了简化插入操作,我们还可以创建一个触发器,当将数据插入到 "TEST" 表的时候,自动将最新的 ID 插入进去。
## 2.创建触发器
```oraclesqlplus
CREATE OR REPLACE TRIGGER TEST_ID_SEQ
BEFORE INSERT ON "TEST"
FOR EACH ROW
BEGIN
  SELECT TEST_ID_SEQ.NEXTVAL
  INTO :NEW."ID"
  FROM DUAL;
END;

插入数据:

SQL> INSERT INTO "TEST" ("ID", "NAME") VALUES (NULL, 'name4');
SQL> INSERT INTO "TEST" ("ID", "NAME") VALUES (NULL, 'name5');
SQL> INSERT INTO "TEST" ("ID", "NAME") VALUES (NULL, 'name6');
SQL> SELECT * FROM "TEST";

ID   NAME
---  ------
100 name1
101 name2
102 name3
103 name4
104 name5
105 name6

3.在MyBatis中运用

<mapper namespace="edp.davinci.dao.UserMapper">

<insert id="insert" parameterType="com.test.Test">
    <!--如果使用了触发器就不需要这一步-->
    <selectKey resultType="java.lang.Long" order="BEFORE" keyProperty="id">
        select TEST_ID_SEQ.NEXTVAL as id from dual 
    </selectKey>
    insert "TEST"
    <trim prefix="(" suffix=")" suffixOverrides=",">
        ID,
        NAME
    </trim>
    values
    <trim prefix=" (" suffix=")" suffixOverrides=",">
        #{ID, jdbcType=BIGINT},
        #{NAME, jdbcType=VARCHAR}

    </trim>
</insert>
</mapper>

4.性能

在数据库操作中,触发器的使用耗费系统资源相对较大。如果对于表容量相对较小的表格我们可以忽略触发器带来的性能影响。

考虑到大表操作的性能问题,需要尽可能的减少触发器的使用。对于以上操作,就可以抛弃触发器的使用,直接手动调用序列函数即可,但这样可能在程序维护上稍微带来一些不便。

三、在Oracle12c中设置自增字段

在 Oracle 12c 中设置自增字段就简单多了,因为 Oracle 12c 提供了 IDENTITY 属性:

CREATE TABLE "TEST" (
    ID NUMBER(11) GENERATED BY DEFAULT ON NULL AS IDENTITY,
    NAME VARCHAR2(50BYTE) NOT NULL
);

这样就搞定了!和 MySQL 一样简单!


文章作者: niww
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 niww !
 上一篇
SpringCloud之application.properties和bootstrap.properties区别 SpringCloud之application.properties和bootstrap.properties区别
一、执行顺序 bootstrap.yml(bootstrap.properties)先加载,application.yml(application.properties)后加载bootstrap.yml(bootstrap.properti
2020-04-03
下一篇 
CRLF导致shell脚本报错 CRLF导致shell脚本报错
问题出现开发的时候在Windows环境中打包了一个rpm包,放到CentOS去执行的时候,当运行start.sh文件的时候,一直报错 “No such file or directory”。 问题原因Linux和Windows文本文件的行结
  目录