在OceanBase 中,实现自增列的4种方法

news2024/11/8 8:50:30

本文作者:杨敬博,爱可生 DBA 团队成员。

背景描述

在OceanBase数据库中,存在MySQL租户与Oracle租户两种模式,本文主要讲解在 OceanBase 的Oracle模式(以下简称OB Oracle),创建自增列的4种方式,并探讨如何以更加简便高效的方式处理自增列的相关问题。

发现问题场景

业务需要将数据库转换为 OceanBase 数据库,但源端涉及到 Oracle 及 MySQL 两种不同数据库,需要合并为 OceanBase 中单一的 Oracle 模式,其中源端 MySQL 数据库需要改造为 OB Oracle 并做异构数据迁移。在数据迁移中发现,MySQL 中的自增列(AUTO_INCREMENT)在 OB Oracle 中是不支持的,在 OB Oracle 对应 MySQL 自增列的功能是通过序列实现的。通过测试以及阅读相关文章,共测试完成了以下四种 OB Oracle 创建并使用序列的方法。

四种 OBOracle 创建序列方法

方法一:SEQUENCE + DML

在 OceanBase 中 Oracle 数据库,我们可以通过以下语法创建序列:

CREATE SEQUENCE sequence_name
    [
        MINVALUE value -- 序列最小值
        MAXVALUE value -- 序列最大值
        START WITH value -- 序列起始值
        INCREMENT BY value -- 序列增长值
        CACHE cache -- 序列缓存个数
        CYCLE | NOCYCLE -- 序列循环或不循环
    ]

语法解释:

  • sequence_name 是要创建的序列名称
  • START WITH 指定使用该序列时要返回的第一个值,默认为 1
  • INCREMENT BY 指定序列每次递增的值,默认为 1
  • MINVALUE 和 MAXVALUE 定义序列值的最小值和最大值
  • CYCLE 表示循环序列
  • NOCYCLE 则表示不循环序列

通过 OB 官方文档操作,创建序列,实现表的列自增,示例如下:

obclient [oboracle]> CREATE TABLE test (
    -> ID NUMBER NOT NULL PRIMARY KEY,
    -> NAME VARCHAR2(480),
    -> AGE NUMBER(10,0)
    -> );
Query OK, 0 rows affected (0.116 sec)

obclient [oboracle]> CREATE SEQUENCE seq_test START WITH 100 INCREMENT BY 1;
Query OK, 0 rows affected (0.026 sec)

obclient [oboracle]> INSERT INTO test(ID,NAME,AGE) VALUES(seq_test.nextval, 'A',18);
Query OK, 1 row affected (0.035 sec)

obclient [oboracle]> INSERT INTO test(ID,NAME,AGE) VALUES(seq_test.nextval, 'B',19);
Query OK, 1 row affected (0.001 sec)

obclient [oboracle]> INSERT INTO test(ID,NAME,AGE) VALUES(seq_test.nextval, 'C',20);
Query OK, 1 row affected (0.001 sec)

obclient [oboracle]> select * from test;
+-----+------+------+
| ID  | NAME | AGE  |
+-----+------+------+
| 100 | A    |   18 |
| 101 | B    |   19 |
| 102 | C    |   20 |
+-----+------+------+
3 rows in set (0.006 sec)

方法二:SEQUENCE + DDL

1、首先创建一个需要自增列的表

obclient [oboracle]> CREATE TABLE Atable (
    ->         ID NUMBER(10,0),
    -> 	   	   NAME VARCHAR2(480),
    ->         AGE NUMBER(10,0),
    ->         PRIMARY KEY (id)
    -> );
Query OK, 0 rows affected (0.105 sec)

obclient [oboracle]> desc Atable;
+-------+---------------+------+-----+---------+-------+
| FIELD | TYPE          | NULL | KEY | DEFAULT | EXTRA |
+-------+---------------+------+-----+---------+-------+
| ID    | NUMBER(10)    | NO   | PRI | NULL     | NULL  |
| NAME  | VARCHAR2(480) | YES  | NULL | NULL    | NULL  |
| AGE   | NUMBER(10)    | YES  | NULL | NULL    | NULL  |
+-------+---------------+------+-----+---------+-------+
3 rows in set (0.037 sec)

2、创建一个序列并更改表中 ID 列的 DEFAULT 属性为 sequence_name.nextval

obclient [oboracle]> CREATE SEQUENCE A_seq
    -> MINVALUE 1
    -> MAXVALUE 999999
    -> START WITH 10
    -> INCREMENT BY 1;
Query OK, 0 rows affected (0.022 sec)

obclient [oboracle]> ALTER TABLE Atable MODIFY id DEFAULT A_seq.nextval;
Query OK, 0 rows affected (0.065 sec)

obclient [oboracle]> desc Atable;
+-------+---------------+------+-----+-------------------+-------+
| FIELD | TYPE          | NULL | KEY | DEFAULT           | EXTRA |
+-------+---------------+------+-----+-------------------+-------+
| ID    | NUMBER(10)    | NO   | PRI | "A_SEQ"."NEXTVAL" | NULL  |
| NAME   | VARCHAR2(480) | YES  | NULL | NULL              | NULL  |
| AGE   | NUMBER(10)    | YES  | NULL | NULL              | NULL  |
+-------+---------------+------+-----+-------------------+-------+
3 rows in set (0.013 sec)

此处为修改表 tablename 中的 ID 值为序列 sequence_name 的下一个值。具体而言,sequence_name.nextval 表示调用 sequence_name 序列的 nextval 函数,该函数返回序列的下一个值。因此,执行述语句后,当 tablename 表中插入一行数据时,会自动为 ID 列赋值为 sequence_name 序列的下一个值。

3、验证该方法是否达到自增列的效果

obclient [oboracle]> INSERT INTO Atable(NAME,AGE) VALUES('zhangsan', 18);
Query OK, 1 row affected (0.047 sec)

obclient [oboracle]> INSERT INTO Atable(NAME,AGE) VALUES('lisi', 19);
Query OK, 1 row affected (0.002 sec)

obclient [oboracle]> select * from Atable;
+----+----------+------+
| ID | AME      | AGE  |
+----+----------+------+
| 10 | zhangsan |   18 |
| 11 | lisi     |   19 |
+----+----------+------+
2 rows in set (0.013 sec)

方法三:SEQUENCE + 触发器

OB 延用 Oracle 中创建触发器的方法达到自增列的效果,具体步骤如下:

1、首先创建一个序列:

obclient [oboracle]> CREATE SEQUENCE B_seq
    -> MINVALUE 1
    -> MAXVALUE 999999
    -> START WITH 1
    -> INCREMENT BY 1;
Query OK, 0 rows affected (0.023 sec)

2、创建一个表:

obclient [oboracle]> CREATE TABLE Btable (
    ->   ID NUMBER,
    ->   NAME VARCHAR2(480),
    ->   AGE NUMBER(10,0)
    -> );
Query OK, 0 rows affected (0.129 sec)

3、创建一个触发器,在每次向表中插入行时,触发器将自动将新行的 ID 列设置为序列的下一个值。

obclient [oboracle]> CREATE OR REPLACE TRIGGER set_id_on_Btable
    -> BEFORE INSERT ON Btable
    -> FOR EACH ROW
    -> BEGIN
    ->   SELECT B_seq.NEXTVAL INTO :new.id FROM dual;
    -> END;
    -> /
Query OK, 0 rows affected (0.114 sec)

该触发器在每次向 Btable 表中插入行之前触发,通过 SELECT B_seq.NEXTVAL INTO :new.id FROM dual; 将 ID 列设置为 B_seq 序列的下一个值。:new.id 表示新插入行的 id 列,dual 是一个虚拟的表,用于生成一行数据用以存储序列的下一个值。

4、验证该方法是否达到自增列的效果

obclient [oboracle]> INSERT INTO Btable(NAME,AGE) VALUES('zhangsan', 18);
Query OK, 1 row affected (0.111 sec)

obclient [oboracle]> INSERT INTO Btable(NAME,AGE) VALUES('lisi', 19);
Query OK, 1 row affected (0.002 sec)

obclient [oboracle]> select * from Btable;
+------+----------+------+
| ID   | NAME     | AGE  |
+------+----------+------+
|    1 | zhangsan |   18 |
|    2 | lisi     |   19 |
+------+----------+------+
2 rows in set (0.008 sec)

方法四:GENERATED BY DEFAULT AS IDENTITY 语法

1、在创建表时使用 GENERATED BY DEFAULT AS IDENTITY 语法来创建自增长的列

obclient [oboracle]> CREATE TABLE Ctable (
    -> ID NUMBER GENERATED BY DEFAULT AS IDENTITY MINVALUE 1 MAXVALUE 999999 INCREMENT BY 1 START WITH 1 primary key,
    -> NAME VARCHAR2(480),
    -> AGE NUMBER(10,0)
    -> );
Query OK, 0 rows affected (0.121 sec)

obclient [oboracle]> desc Ctable;
+-------+---------------+------+-----+------------------+-------+
| FIELD | TYPE          | NULL | KEY | DEFAULT          | EXTRA |
+-------+---------------+------+-----+------------------+-------+
| ID    | NUMBER        | NO   | PRI | SEQUENCE.NEXTVAL | NULL  |
| NAME  | VARCHAR2(480) | YES  | NULL | NULL             | NULL  |
| AGE   | NUMBER(10)    | YES  | NULL | NULL             | NULL  |
+-------+---------------+------+-----+------------------+-------+
3 rows in set (0.011 sec)

2、验证该方法是否达到自增列的效果

obclient [oboracle]> INSERT INTO Ctable(NAME,AGE) VALUES('zhangsan', 18);
Query OK, 1 row affected (0.015 sec)

obclient [oboracle]> INSERT INTO Ctable(NAME,AGE) VALUES('lisi', 19);
Query OK, 1 row affected (0.001 sec)

obclient [oboracle]> select * from Ctable;
+----+----------+------+
| ID | NAME     | AGE  |
+----+----------+------+
| 1  | zhangsan |   18 |
| 2  | lisi     |   19 |
+----+----------+------+
2 rows in set (0.008 sec)

3、通过验证,使用 GENERATED BY DEFAULT AS IDENTITY 可以非常简单地创建自增长列,无需使用其他手段,例如触发器。此方法不需要手动创建序列,会自动创建一个序列,在内部使用它来生成自增长列的值。

obclient [SYS]>  select * from dba_objects where OBJECT_TYPE='SEQUENCE';
+-------+-----------------+----------------+------------------+----------------+-------------+-----------+---------------+------------------------------+--------+-----------+-----------+-----------+-----------+--------------+
| OWNER | OBJECT_NAME     | SUBOBJECT_NAME | OBJECT_ID        | DATA_OBJECT_ID | OBJECT_TYPE | CREATED   | LAST_DDL_TIME | TIMESTAMP                    | STATUS | TEMPORARY | GENERATED | SECONDARY | NAMESPACE | EDITION_NAME |
+-------+-----------------+----------------+------------------+----------------+-------------+-----------+---------------+------------------------------+--------+-----------+-----------+-----------+-----------+--------------+
| MYSQL | A_SEQ           | NULL           | 1100611139403783 |           NULL | SEQUENCE    | 31-MAY-23 | 31-MAY-23     | 31-MAY-23 02.21.42.603005 PM | VALID  | N         | N         | N         |         0 | NULL         |
| MYSQL | B_SEQ           | NULL           | 1100611139403784 |           NULL | SEQUENCE    | 31-MAY-23 | 31-MAY-23     | 31-MAY-23 03.28.39.222090 PM | VALID  | N         | N         | N         |         0 | NULL         |
| MYSQL | ISEQ$$_50012_16 | NULL           | 1100611139403785 |           NULL | SEQUENCE    | 31-MAY-23 | 31-MAY-23     | 31-MAY-23 04.01.23.577766 PM | VALID  | N         | N         | N         |         0 | NULL         |
| MYSQL | SEQ_TEST        | NULL           | 1100611139403786 |           NULL | SEQUENCE    | 31-MAY-23 | 31-MAY-23     | 31-MAY-23 05.09.33.981039 PM | VALID  | N         | N         | N         |         0 | NULL         |
+-------+-----------------+----------------+------------------+----------------+-------------+-----------+---------------+------------------------------+--------+-----------+-----------+-----------+-----------+--------------+
6 rows in set (0.042 sec)

查看数据库对象视图 dba_objects,发现该方法通过创建对象内部命名方式为 ISEQ$$_5000x_16

测试发现,关于序列对象的名称在OB中不论是通过 GENERATED BY DEFAULT AS IDENTITY 自动创建,还是手动创建,都会占用 ISEQ$$_5000x_16 中 x 的位置,若删除序列或删除表,该对象名称也不会复用,只会单调递增。

Tips:在 Oracle 12c 及以上版本中,可以使用 GENERATED BY DEFAULT AS IDENTITY 关键字来创建自增长的列;在 PostgreSQL 数据库中 GENERATED BY DEFAULT AS IDENTITY 也是适用的。

总结

  • 方法一(SEQUENCE + DML):也就是 OB 的官方文档中创建序列的操作,在每次做 INSERT 操作时需要指定自增列并加入 sequence_name ,对业务不太友好,不推荐。
  • 方法二(SEQUENCE + DDL):相较于第一种该方法只需要指定 DDL 改写 DEFAULT 属性省去了 DML 的操作,但仍需再指定自己创建的序列名 sequence_name,每个表的序列名都不一致,管理不方便,不推荐。
  • 方法三(SEQUENCE + 触发器)延用 Oracle 的序列加触发器的方法,触发器会占用更多的计算资源和内存,对性能会有影响,因此也不推荐。
  • 方法四(GENERATED BY DEFAULT AS IDENTITY 语法):既方便运维人员管理,对业务也很友好,还不影响性能。强烈推荐!!!

以上就是对 OBOracle 中如何创建自增列的几种方法的总结。有需要的小伙伴可以试试(●’◡’●)。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2235695.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

KV260 - PYNQ 主目录 - U盘挂载

目录 1. 简介 2. 具体操作 2.1 查看 USB 设备 2.2 查看 U 盘设备节点 2.3 挂载 U 盘到指定目录 2.4 查看挂载状态 2.5 卸载 U 盘 3. 总结 1. 简介 在 KV260 使用 Jupyter Lab 可以非常方便开发各种应用。有时不方便在 PC 端连接 U 盘,那么可以把 U 盘连在 …

金媒婚恋相亲系统10.4择爱开源旗舰版支持微信小程和抖音小程序上架

最近大家应该注意到了,金媒婚恋相亲系统已经更新至最新的10.4版本了!本人作为商业用户也已经更新至最新的旗舰版了,更新的内容是啥!这个官方都有列出,一个方面就是更新了多端的登录逻辑和UI 和后台CRM及很多细节的优化…

用环形数组实现队列(多种高级方法,由浅入深)

同普通数组实现的队列相比,普通数组的头结点和尾节点都是固定的,在进行移除的时候如果移除了一个节点,后面所有节点都需要进行移除操作,需要的时间复杂度更高 在环形数组中,确定了头尾指针的环形数组很好地解决了这一…

【毫米波雷达(七)】自动驾驶汽车中的精准定位——RTK定位技术

一、什么是RTK? RTK,英文全名叫做Real-time kinematic,也就是实时动态。这是一个简称,全称其实应该是RTK(Real-time kinematic,实时动态)载波相位差分技术。 二、RTK的组装 如上图所示&#x…

小北的字节跳动青训营与调用模型:调用模型:OpenAI API vs 微调开源Llama2/ChatGLM(持续更新中~~~)

前言 最近,字节跳动的青训营再次扬帆起航,作为第二次参与其中的小北,深感荣幸能借此机会为那些尚未了解青训营的友友们带来一些详细介绍。青训营不仅是一个技术学习与成长的摇篮,更是一个连接未来与梦想的桥梁~ 小北的青训营 X M…

通过DNS服务器架构解释DNS请求过程

在前面的章节,这里,基于PCAP数据包和RFC文档详细介绍了DNS请求和响应的每个字段的含义。但是在现实的网络世界中,DNS请求和响应的数据包是怎么流动的,会经过哪些设备。本文将着重说明一下目前网络空间中DNS请求和响应的流动过程。…

Netty实现WebSocket Server是否开启压缩深度分析

是否开启压缩会直接影响与客户端是否能够成功握手。 一、具体分析 通常客户端发起与Websocket连接一般是以下形式。 1)包含6个必要的Header Request Headers Sec-WebSocket-Version: 13 Sec-WebSocket-Key: Nlpc0kiHFjRom5/62lj8bA Connection: Upgrade Upgrade…

IntelliJ IDEA 2023.2——配置说明

IntelliJ IDEA 2023.2——配置说明 IntelliJ IDEA 的官方下载地址 IntelliJ IDEA 官网下载地址 一路上NEXT 到结尾: 继续NEXT 下一步: 界面如下图所示 界面如下图所示 ctrl F 查找 “码猿趣事” 查找【idea99】

算法通关(4)-- 前缀树

前缀数原理和代码 原理 前缀树(Trie树),也称为字典树,是一种用于高效存储和检索字符串的数据结构。它是一种树形结构,能够利用字符串的公共前缀来减少存储空间和查询时间。 现在有“acb”,"cba","ac…

【CSS】“flex: 1“有什么用?

flex 属性的组成 flex 属性是一个复合属性,包含以下三个子属性: flex-grow:决定元素在容器中剩余空间的分配比例。默认值为 0,表示元素不会扩展。当设置为正数时,元素会按照设定比例扩展。flex-shrink:决…

【dvwa靶场:XSS系列】XSS (Stored)低-中-高级别,通关啦

更改name的文本数量限制大小&#xff0c; 其他我们只在name中进行操作 【除了低级可以在message中进行操作】 一、低级low <script>alert("假客套")</script> 二、中级middle 过滤了小写&#xff0c;咱们可以大写 <Script>alert("假客套…

大数据-212 数据挖掘 机器学习理论 - 无监督学习算法 KMeans 基本原理 簇内误差平方和

点一下关注吧&#xff01;&#xff01;&#xff01;非常感谢&#xff01;&#xff01;持续更新&#xff01;&#xff01;&#xff01; 目前已经更新到了&#xff1a; Hadoop&#xff08;已更完&#xff09;HDFS&#xff08;已更完&#xff09;MapReduce&#xff08;已更完&am…

神经网络基础--什么是正向传播??什么是方向传播??

前言 本专栏更新神经网络的一些基础知识&#xff1b;这个是本人初学神经网络做的笔记&#xff0c;仅仅堆正向传播、方向传播就行了了一个讲解&#xff0c;更加系统的讲解&#xff0c;本人后面会更新《李沐动手学习深度学习》&#xff0c;会更有详细讲解;案例代码基于pytorch&a…

【大模型系列】Grounded-VideoLLM(2024.10)

Paper&#xff1a;https://arxiv.org/pdf/2410.03290Github&#xff1a;https://github.com/WHB139426/Grounded-Video-LLMHuggingface&#xff1a;https://huggingface.co/WHB139426/Grounded-Video-LLMAuthor&#xff1a;Haibo Wang et al. 加州大学&#xff0c;复旦 动机&a…

IDEA2024下安装kubernetes插件并配置进行使用

【1】安装插件 其实2024.2.3下默认已经安装了kubernetes插件&#xff0c;如果你发现自己IDEA中没有&#xff0c;在市场里面检索并下载即可。 【2】kubernetes配置 ① 前置工作 首先你要准备一个config文件和一个kubectl.exe 。 config文件类似如下&#xff1a; apiVersi…

onnx-web + yolov8n 在视频流里做推理

顺着我上一篇文章 使用onnxruntime-web 运行yolov8-nano推理 继续说&#xff0c;有朋友在问能不能接入 视频流动&#xff0c;实时去识别物品。 首先使用 getUserMedia 获取摄像头视频流 getUserMedia API 可以访问设备的摄像头和麦克风。你可以使用这个 API 获取视频流&#…

Python练习11

Python日常练习 题目&#xff1a; 编写一个石头剪刀布游戏&#xff0c;该程序要求完成如下功能&#xff1a; (1) 显示游戏规则&#xff0c;提醒用户输入一个1-3的整数或者直接回车。 用户输入回车时游戏结束。 用户输入不合法&#xff08;包括输入的…

航展畅想:从F35机载软件研发来看汽车车载软件研发

两款经典战机的机载软件 F-22和F-35战斗机的研制分别始于1980年代和1990年代末&#xff0c;F-22项目在1981年启动&#xff0c;主要由洛克希德马丁&#xff08;Lockheed Martin&#xff09;和波音公司&#xff08;Boeing&#xff09;合作开发&#xff0c;以满足美军“先进战术战…

实践出真知:MVEL表达式empty的坑

目录标题 背景为什么呢&#xff1f;验证下empty的含义case1case2case3 结论具体解释&#xff1a; 背景 //是否白名单 if(goodInfo.?isWhite ! empty){showList.add(["label": "是否白名单","value":["text":(goodInfo.?isWhite tr…

RPC核心实现原理

目录 一、基本原理 二、详细步骤 三、额外考虑因素 RPC&#xff08;Remote Procedure Call&#xff0c;远程过程调用&#xff09;是一种计算机通信协议&#xff0c;也是一种用于实现分布式系统中不同节点之间进行通信和调用的技术。其实现原理主要可以分为以下几个步骤&…