当前位置: 首页 > news >正文

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

本文作者:杨敬博,爱可生 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 中如何创建自增列的几种方法的总结。有需要的小伙伴可以试试(●’◡’●)。

相关文章:

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

本文作者:杨敬博,爱可生 DBA 团队成员。 背景描述 在OceanBase数据库中,存在MySQL租户与Oracle租户两种模式,本文主要讲解在 OceanBase 的Oracle模式(以下简称OB Oracle),创建自增列的4种方式&…...

LWE算法分类及基本加解密算法示例

LWE(Learning With Errors)算法是一种基于格(lattice)的密码学原语,广泛应用于构建抗量子计算的加密方案。LWE算法的安全性基于最坏情况下的格问题(如最短向量问题SVP和最近向量问题CVP)&#x…...

【论文阅读】Learning dynamic alignment via meta-filter for few-shot learning

通过元滤波器学习动态对齐以实现小样本学习 引用:Xu C, Fu Y, Liu C, et al. Learning dynamic alignment via meta-filter for few-shot learning[C]//Proceedings of the IEEE/CVF conference on computer vision and pattern recognition. 2021: 5182-5191. 论文…...

蓝牙 SPP 协议详解及 Android 实现

文章目录 前言一、 什么是蓝牙 SPP 协议?SPP 的适用场景 二、SPP的工作流程1. 蓝牙设备初始化2. 设备发现与配对3. 建立 SPP 连接4. 数据传输5. 关闭连接 三、进阶应用与常见问题蓝牙连接中断与重试机制数据传输中的延迟与错误处理电池消耗和蓝牙优化 总结 前言 蓝…...

系统学习领域驱动设计-感悟-高尚名词篇

高尚名词 高尚名词通俗意思知识消化开发代码过程中的业务理解持续学习团队角度,持续沉淀文档沉淀业务理解,教会更多的新人,不让某些员工掌握知识壁垒...

人工智能(AI)和机器学习(ML)技术学习流程

目录 人工智能(AI)和机器学习(ML)技术 自然语言处理(NLP): Word2Vec: Seq2Seq(Sequence-to-Sequence): Transformer: 范式、架构和自注意力: 多头注意力: 预训练、微调、提示工程和模型压缩: 上下文学习、思维链、全量微调、量化、剪枝: 思维树、思维…...

<Project-20 YT-DLP> 给视频网站下载工具 yt-dlp/yt-dlp 加个页面 python web

介绍 yt-dlp Github 项目:https://github.com/yt-dlp/yt-dlp A feature-rich command-line audio/video downloader 一个功能丰富的视频与音频命令行下载器 原因与功能 之前我用的 cobalt 因为它不再提供Client Web功能,只能去它的官网使用。 翻 redd…...

【Android】Gradle 7.0+ 渠道打包配置

声明 该配置主要解决打包apk/aab需要动态修改渠道字段,方便区分渠道上架国内商店。 暂不支持批量打包(7.4版本无法通过只修改outputFileName的形式批量处理) 因为构建时需要拷贝/创建Output,然后修改outputFileName才能处理批量打包,但拷贝/创建在高版本中失效了。 目前的…...

Web应用性能测试工具 - httpstat

在数字化时代,网站的性能直接影响用户体验和业务成功。你是否曾经在浏览网页时,遇到加载缓慢的困扰?在这个快速变化的互联网环境中,如何快速诊断和优化Web应用的性能呢?今天,我们将探讨一个强大的工具——h…...

MySQL 【流程控制】函数

目录 1、CASE 语句用于流程控制中的多分支情况。 2、IF() 函数根据测试条件是否为真分别返回指定的值。 3、IFNULL() 函数,如果第一个参数为 NULL,返回第二个参数,否则返回第一个参数。 4、NULLIF() 函数根据两个参数是否相等决定返回 NUL…...

python 天气数据可视化

Python爬取天气数据及可视化分析 https://blog.csdn.net/weixin_69423932/article/details/135184643...

【HarmonyOS Next】数据本地存储:@ohos.data.preferences

【HarmonyOS Next】数据本地存储:ohos.data.preferences 在开发现代应用程序时,数据存储是一个至关重要的过程。应用程序为了保持某些用户设置、应用状态以及其他小量数据信息通常需要一个可靠的本地存储解决方案。在 HarmonyOS Next 环境下&#xff0c…...

使用BaGet快速搭建nuget服务

BaGet是基于 asp.net core编写的一个轻量级的 nuget管理服务,安装部署非常简单。 * Nuget版本号规范:https://learn.microsoft.com/zh-cn/nuget/concepts/package-versioning。 环境准备 下载 BaGet安装包。 https://loic-sharma.github.io/BaGet/ 下…...

基于Zynq FPGA的雷龙SD NAND存储芯片性能测试

文章目录 前言一、SD NAND特征1.1 SD卡简介1.2 SD卡Block图 二、SD卡样片三、Zynq测试平台搭建3.1 测试流程3.2 SOC搭建 四、软件搭建五、测试结果六、总结 前言 随着嵌入式系统和物联网设备的快速发展,高效可靠的存储解决方案变得越来越重要。雷龙发展推出的SD NA…...

【功能介绍】信创终端系统上各WPS版本的授权差异

原文链接:【功能介绍】信创终端系统上各WPS版本的授权差异 Hello,大家好啊!今天给大家带来一篇关于信创终端操作系统上WPS Office各版本(不包括政务版、企业版等)之间的差异的文章。WPS Office作为国内广泛使用的办公软…...

Neo4j 和 Python 初学者指南:如何使用可选关系匹配优化 Cypher 查询

Neo4j 和 Python 初学者指南:如何使用可选关系匹配优化 Cypher 查询 查询需求分析目标查询结构 编写 Cypher 查询查询解析OPTIONAL MATCH 和 COALESCE 的作用 在 Python 中使用 Neo4j 驱动执行查询使用 neo4j 驱动的 Python 示例代码代码解析示例输出 总结 在使用 N…...

性能测试|docker容器下搭建JMeter+Grafana+Influxdb监控可视化平台

前言 在当前激烈的市场竞争中,创新和效率成为企业发展的核心要素之一。在这种背景下,如何保证产品和服务的稳定性、可靠性以及高效性就显得尤为重要。 而在软件开发过程中,性能测试是一项不可或缺的环节,它可以有效的评估一个系…...

(vue3)在Pinia Store中正确使用Vue I18n

引言 在Vue 3和Pinia的开发过程中,我们经常需要在store中使用国际化(i18n)功能。然而,这个看似简单的任务可能会导致一些棘手的问题。本文将深入探讨在Pinia store中使用Vue I18n时可能遇到的挑战,解释问题的根源&…...

如何开发查找附近地点的微信小程序

我开发的是找附近卫生间的小程序。 在现代城市生活中,找到一个干净、方便的公共卫生间有时可能是一个挑战。为了解决这个问题,我们可以开发一款微信小程序,帮助用户快速找到附近的卫生间。本文将介绍如何开发这样一款小程序,包…...

三格电子——电梯监测状态项目

方案介绍...

深入剖析AI大模型:大模型时代的 Prompt 工程全解析

今天聊的内容,我认为是AI开发里面非常重要的内容。它在AI开发里无处不在,当你对 AI 助手说 "用李白的风格写一首关于人工智能的诗",或者让翻译模型 "将这段合同翻译成商务日语" 时,输入的这句话就是 Prompt。…...

从深圳崛起的“机器之眼”:赴港乐动机器人的万亿赛道赶考路

进入2025年以来,尽管围绕人形机器人、具身智能等机器人赛道的质疑声不断,但全球市场热度依然高涨,入局者持续增加。 以国内市场为例,天眼查专业版数据显示,截至5月底,我国现存在业、存续状态的机器人相关企…...

工业自动化时代的精准装配革新:迁移科技3D视觉系统如何重塑机器人定位装配

AI3D视觉的工业赋能者 迁移科技成立于2017年,作为行业领先的3D工业相机及视觉系统供应商,累计完成数亿元融资。其核心技术覆盖硬件设计、算法优化及软件集成,通过稳定、易用、高回报的AI3D视觉系统,为汽车、新能源、金属制造等行…...

在鸿蒙HarmonyOS 5中使用DevEco Studio实现录音机应用

1. 项目配置与权限设置 1.1 配置module.json5 {"module": {"requestPermissions": [{"name": "ohos.permission.MICROPHONE","reason": "录音需要麦克风权限"},{"name": "ohos.permission.WRITE…...

使用Matplotlib创建炫酷的3D散点图:数据可视化的新维度

文章目录 基础实现代码代码解析进阶技巧1. 自定义点的大小和颜色2. 添加图例和样式美化3. 真实数据应用示例实用技巧与注意事项完整示例(带样式)应用场景在数据科学和可视化领域,三维图形能为我们提供更丰富的数据洞察。本文将手把手教你如何使用Python的Matplotlib库创建引…...

CSS设置元素的宽度根据其内容自动调整

width: fit-content 是 CSS 中的一个属性值&#xff0c;用于设置元素的宽度根据其内容自动调整&#xff0c;确保宽度刚好容纳内容而不会超出。 效果对比 默认情况&#xff08;width: auto&#xff09;&#xff1a; 块级元素&#xff08;如 <div>&#xff09;会占满父容器…...

Netty从入门到进阶(二)

二、Netty入门 1. 概述 1.1 Netty是什么 Netty is an asynchronous event-driven network application framework for rapid development of maintainable high performance protocol servers & clients. Netty是一个异步的、基于事件驱动的网络应用框架&#xff0c;用于…...

C#中的CLR属性、依赖属性与附加属性

CLR属性的主要特征 封装性&#xff1a; 隐藏字段的实现细节 提供对字段的受控访问 访问控制&#xff1a; 可单独设置get/set访问器的可见性 可创建只读或只写属性 计算属性&#xff1a; 可以在getter中执行计算逻辑 不需要直接对应一个字段 验证逻辑&#xff1a; 可以…...

django blank 与 null的区别

1.blank blank控制表单验证时是否允许字段为空 2.null null控制数据库层面是否为空 但是&#xff0c;要注意以下几点&#xff1a; Django的表单验证与null无关&#xff1a;null参数控制的是数据库层面字段是否可以为NULL&#xff0c;而blank参数控制的是Django表单验证时字…...

【前端异常】JavaScript错误处理:分析 Uncaught (in promise) error

在前端开发中&#xff0c;JavaScript 异常是不可避免的。随着现代前端应用越来越多地使用异步操作&#xff08;如 Promise、async/await 等&#xff09;&#xff0c;开发者常常会遇到 Uncaught (in promise) error 错误。这个错误是由于未正确处理 Promise 的拒绝&#xff08;r…...