在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指定使用该序列时要返回的第一个值,默认为 1INCREMENT BY指定序列每次递增的值,默认为 1MINVALUE和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 环境下,…...
使用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时可能遇到的挑战,解释问题的根源&…...
如何开发查找附近地点的微信小程序
我开发的是找附近卫生间的小程序。 在现代城市生活中,找到一个干净、方便的公共卫生间有时可能是一个挑战。为了解决这个问题,我们可以开发一款微信小程序,帮助用户快速找到附近的卫生间。本文将介绍如何开发这样一款小程序,包…...
三格电子——电梯监测状态项目
方案介绍...
基于算法竞赛的c++编程(28)结构体的进阶应用
结构体的嵌套与复杂数据组织 在C中,结构体可以嵌套使用,形成更复杂的数据结构。例如,可以通过嵌套结构体描述多层级数据关系: struct Address {string city;string street;int zipCode; };struct Employee {string name;int id;…...
三维GIS开发cesium智慧地铁教程(5)Cesium相机控制
一、环境搭建 <script src"../cesium1.99/Build/Cesium/Cesium.js"></script> <link rel"stylesheet" href"../cesium1.99/Build/Cesium/Widgets/widgets.css"> 关键配置点: 路径验证:确保相对路径.…...
深入浅出:JavaScript 中的 `window.crypto.getRandomValues()` 方法
深入浅出:JavaScript 中的 window.crypto.getRandomValues() 方法 在现代 Web 开发中,随机数的生成看似简单,却隐藏着许多玄机。无论是生成密码、加密密钥,还是创建安全令牌,随机数的质量直接关系到系统的安全性。Jav…...
vue3 字体颜色设置的多种方式
在Vue 3中设置字体颜色可以通过多种方式实现,这取决于你是想在组件内部直接设置,还是在CSS/SCSS/LESS等样式文件中定义。以下是几种常见的方法: 1. 内联样式 你可以直接在模板中使用style绑定来设置字体颜色。 <template><div :s…...
React---day11
14.4 react-redux第三方库 提供connect、thunk之类的函数 以获取一个banner数据为例子 store: 我们在使用异步的时候理应是要使用中间件的,但是configureStore 已经自动集成了 redux-thunk,注意action里面要返回函数 import { configureS…...
根目录0xa0属性对应的Ntfs!_SCB中的FileObject是什么时候被建立的----NTFS源代码分析--重要
根目录0xa0属性对应的Ntfs!_SCB中的FileObject是什么时候被建立的 第一部分: 0: kd> g Breakpoint 9 hit Ntfs!ReadIndexBuffer: f7173886 55 push ebp 0: kd> kc # 00 Ntfs!ReadIndexBuffer 01 Ntfs!FindFirstIndexEntry 02 Ntfs!NtfsUpda…...
Python 训练营打卡 Day 47
注意力热力图可视化 在day 46代码的基础上,对比不同卷积层热力图可视化的结果 import torch import torch.nn as nn import torch.optim as optim from torchvision import datasets, transforms from torch.utils.data import DataLoader import matplotlib.pypl…...
离线语音识别方案分析
随着人工智能技术的不断发展,语音识别技术也得到了广泛的应用,从智能家居到车载系统,语音识别正在改变我们与设备的交互方式。尤其是离线语音识别,由于其在没有网络连接的情况下仍然能提供稳定、准确的语音处理能力,广…...
高端性能封装正在突破性能壁垒,其芯片集成技术助力人工智能革命。
2024 年,高端封装市场规模为 80 亿美元,预计到 2030 年将超过 280 亿美元,2024-2030 年复合年增长率为 23%。 细分到各个终端市场,最大的高端性能封装市场是“电信和基础设施”,2024 年该市场创造了超过 67% 的收入。…...
【Ftrace 专栏】Ftrace 参考博文
ftrace、perf、bcc、bpftrace、ply、simple_perf的使用Ftrace 基本用法Linux 利用 ftrace 分析内核调用如何利用ftrace精确跟踪特定进程调度信息使用 ftrace 进行追踪延迟Linux-培训笔记-ftracehttps://www.kernel.org/doc/html/v4.18/trace/events.htmlhttps://blog.csdn.net/…...
