0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

从MySQL到OBOracle:如何处理自增列?

OSC开源社区 来源:爱可生开源社区 2023-06-11 15:40 次阅读

1 背景描述

OceanBase 数据库中分为 MySQL 租户与 Oracle 租户,本文针对 OceanBase 中 Oracle 租户怎样创建自增列,以及如何更简单方便的处理自增列的问题展开介绍。OceanBase 的 Oracle 租户以下简称:OBOracle

发现问题场景

业务需要将数据库转换为 OceanBase 数据库,但源端涉及到 Oracle 及 MySQL 两种不同数据库,需要合并为 OceanBase 中单一的 Oracle 模式,其中源端 MySQL 数据库需要改造为 OBOracle 并做异构数据迁移。

在数据迁移中发现,MySQL 中的自增列(AUTO_INCREMENT)在 OBOracle 中是不支持的,在 OBOracle 对应 MySQL 自增列的功能是通过序列实现的。通过测试以及阅读相关文章,共测试完成了以下四种 OBOracle 创建并使用序列的方法。

2 四种 OBOracle 创建序列方法

1方法一:SEQUENCE + DML

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

CREATESEQUENCEsequence_name
[
MINVALUEvalue--序列最小值
MAXVALUEvalue--序列最大值
STARTWITHvalue--序列起始值
INCREMENTBYvalue--序列增长值
CACHEcache--序列缓存个数
CYCLE|NOCYCLE--序列循环或不循环
]

语法解释:

sequence_name 是要创建的序列名称

START WITH 指定使用该序列时要返回的第一个值,默认为 1

INCREMENT BY 指定序列每次递增的值,默认为 1

MINVALUE 和 MAXVALUE 定义序列值的最小值和最大值

如果序列已经递增到最大值或最小值,则会根据你的设置进行循环或停止自增长。CACHE设置序列预读缓存数量。

CYCLE 表示循环序列

NOCYCLE 则表示不循环序列

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

obclient[oboracle]>CREATETABLEtest(
->IDNUMBERNOTNULLPRIMARYKEY,
->NAMEVARCHAR2(480),
->AGENUMBER(10,0)
->);
QueryOK,0rowsaffected(0.116sec)

obclient[oboracle]>CREATESEQUENCEseq_testSTARTWITH100INCREMENTBY1;
QueryOK,0rowsaffected(0.026sec)

obclient[oboracle]>INSERTINTOtest(ID,NAME,AGE)VALUES(seq_test.nextval,'A',18);
QueryOK,1rowaffected(0.035sec)

obclient[oboracle]>INSERTINTOtest(ID,NAME,AGE)VALUES(seq_test.nextval,'B',19);
QueryOK,1rowaffected(0.001sec)

obclient[oboracle]>INSERTINTOtest(ID,NAME,AGE)VALUES(seq_test.nextval,'C',20);
QueryOK,1rowaffected(0.001sec)

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

2方法二:SEQUENCE + DDL

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

obclient[oboracle]>CREATETABLEAtable(
->IDNUMBER(10,0),
->NAMEVARCHAR2(480),
->AGENUMBER(10,0),
->PRIMARYKEY(id)
->);
QueryOK,0rowsaffected(0.105sec)

obclient[oboracle]>descAtable;
+-------+---------------+------+-----+---------+-------+
|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|
+-------+---------------+------+-----+---------+-------+
3rowsinset(0.037sec)

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

obclient[oboracle]>CREATESEQUENCEA_seq
->MINVALUE1
->MAXVALUE999999
->STARTWITH10
->INCREMENTBY1;
QueryOK,0rowsaffected(0.022sec)

obclient[oboracle]>ALTERTABLEAtableMODIFYidDEFAULTA_seq.nextval;
QueryOK,0rowsaffected(0.065sec)

obclient[oboracle]>descAtable;
+-------+---------------+------+-----+-------------------+-------+
|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|
+-------+---------------+------+-----+-------------------+-------+
3rowsinset(0.013sec)

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

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

obclient[oboracle]>INSERTINTOAtable(NAME,AGE)VALUES('zhangsan',18);
QueryOK,1rowaffected(0.047sec)

obclient[oboracle]>INSERTINTOAtable(NAME,AGE)VALUES('lisi',19);
QueryOK,1rowaffected(0.002sec)

obclient[oboracle]>select*fromAtable;
+----+----------+------+
|ID|AME|AGE|
+----+----------+------+
|10|zhangsan|18|
|11|lisi|19|
+----+----------+------+
2rowsinset(0.013sec)

3 方法三:SEQUENCE + 触发器

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

1、首先创建一个序列。

obclient[oboracle]>CREATESEQUENCEB_seq
->MINVALUE1
->MAXVALUE999999
->STARTWITH1
->INCREMENTBY1;
QueryOK,0rowsaffected(0.023sec)

2、创建一个表。

obclient[oboracle]>CREATETABLEBtable(
->IDNUMBER,
->NAMEVARCHAR2(480),
->AGENUMBER(10,0)
->);
QueryOK,0rowsaffected(0.129sec)

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

obclient[oboracle]>CREATEORREPLACETRIGGERset_id_on_Btable
->BEFOREINSERTONBtable
->FOREACHROW
->BEGIN
->SELECTB_seq.NEXTVALINTO:new.idFROMdual;
->END;
->/
QueryOK,0rowsaffected(0.114sec)

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

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

obclient[oboracle]>INSERTINTOBtable(NAME,AGE)VALUES('zhangsan',18);
QueryOK,1rowaffected(0.111sec)

obclient[oboracle]>INSERTINTOBtable(NAME,AGE)VALUES('lisi',19);
QueryOK,1rowaffected(0.002sec)

obclient[oboracle]>select*fromBtable;
+------+----------+------+
|ID|NAME|AGE|
+------+----------+------+
|1|zhangsan|18|
|2|lisi|19|
+------+----------+------+
2rowsinset(0.008sec)

4方法四:GENERATED BY DEFAULT AS IDENTITY 语法

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

obclient[oboracle]>CREATETABLECtable(
->IDNUMBERGENERATEDBYDEFAULTASIDENTITYMINVALUE1MAXVALUE999999INCREMENTBY1STARTWITH1primarykey,
->NAMEVARCHAR2(480),
->AGENUMBER(10,0)
->);
QueryOK,0rowsaffected(0.121sec)

obclient[oboracle]>descCtable;
+-------+---------------+------+-----+------------------+-------+
|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|
+-------+---------------+------+-----+------------------+-------+
3rowsinset(0.011sec)

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

obclient[oboracle]>INSERTINTOCtable(NAME,AGE)VALUES('zhangsan',18);
QueryOK,1rowaffected(0.015sec)

obclient[oboracle]>INSERTINTOCtable(NAME,AGE)VALUES('lisi',19);
QueryOK,1rowaffected(0.001sec)

obclient[oboracle]>select*fromCtable;
+----+----------+------+
|ID|NAME|AGE|
+----+----------+------+
|1|zhangsan|18|
|2|lisi|19|
+----+----------+------+
2rowsinset(0.008sec)

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

obclient[SYS]>select*fromdba_objectswhereOBJECT_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-2302.21.42.603005PM|VALID|N|N|N|0|NULL|
|MYSQL|B_SEQ|NULL|1100611139403784|NULL|SEQUENCE|31-MAY-23|31-MAY-23|31-MAY-2303.28.39.222090PM|VALID|N|N|N|0|NULL|
|MYSQL|ISEQ$$_50012_16|NULL|1100611139403785|NULL|SEQUENCE|31-MAY-23|31-MAY-23|31-MAY-2304.01.23.577766PM|VALID|N|N|N|0|NULL|
|MYSQL|SEQ_TEST|NULL|1100611139403786|NULL|SEQUENCE|31-MAY-23|31-MAY-23|31-MAY-2305.09.33.981039PM|VALID|N|N|N|0|NULL|
+-------+-----------------+----------------+------------------+----------------+-------------+-----------+---------------+------------------------------+--------+-----------+-----------+-----------+-----------+--------------+
6rowsinset(0.042sec)

查看数据库对象视图 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 也是适用的。

3 总结

方法一(SEQUENCE + DML):也就是 OB 的官方文档中创建序列的操作,在每次做 INSERT 操作时需要指定自增列并加入 sequence_name ,对业务不太友好,推荐

方法二(SEQUENCE + DDL):相较于第一种该方法只需要指定 DDL 改写 DEFAULT 属性省去了 DML 的操作,但仍需再指定自己创建的序列名 sequence_name,每个表的序列名都不一致,管理不方便,不推荐

方法三(SEQUENCE + 触发器):延用 Oracle 的序列加触发器的方法,触发器会占用更多的计算资源和内存,对性能会有影响,因此也不推荐

方法四(GENERATED BY DEFAULT AS IDENTITY 语法):既方便运维人员管理,对业务也很友好,还不影响性能。强烈推荐!!!

以上就是对 OBOracle 中如何创建自增列的几种方法的总结。




审核编辑:刘清

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • 触发器
    +关注

    关注

    14

    文章

    1996

    浏览量

    61055
  • Oracle
    +关注

    关注

    2

    文章

    288

    浏览量

    35101
  • DDL
    DDL
    +关注

    关注

    0

    文章

    12

    浏览量

    6320
  • MYSQL数据库
    +关注

    关注

    0

    文章

    95

    浏览量

    9382

原文标题:从MySQL到OBOracle:如何处理自增列?

文章出处:【微信号:OSC开源社区,微信公众号:OSC开源社区】欢迎添加关注!文章转载请注明出处。

收藏 人收藏

    评论

    相关推荐

    怎么简单实现由Labview读取的串口数据增写入mysql5.7数据库中?

    怎么简单实现由Labview读取的串口数据增写入mysql5.7数据库中? 已实现:串口数据的接收处理 mysql5.7的安装(已测试数据库正常运行) 愿付费解决此问题(QQ:8
    发表于 01-11 22:05

    mysql中文参考手册chm

    的信息 8.6 以批处理模式使用mysql 8.7 "双胞项目"中查询 8.7.1 找出所有非独处的双胞胎 8.7.2 显示关于双胞胎近况的表 9 MySQL 服务器功能 9.1
    发表于 12-26 13:32

    全球唯一:MySQL社区2018年度公司贡献奖颁给阿里云

    中。6. 增列值持久化MySQL AUTO_INCREMENT 字段实现了增 ID 的生成,但只保存在内存中,意外宕机或重启,就会丢失
    发表于 04-25 11:51

    labview与MySQL的读写,配置操作,十分详细的教程。

    ODBC创建数据源名(DSN),MySQL的ODBC驱动的安装,读写MySQL的一些小技巧,以及一些基础应用,文件中附有PDF教程,及labview读写范例,教你一步步完成操作,教
    发表于 07-16 11:00

    移植MysqlARM平台

    本帖最后由 辉绿荫跑道 于 2020-10-20 17:03 编辑 目前我使用的Mysql的版本为mysql-5.1.72.tar.gz,可在网上下载对应版本的mysql的压缩包。由于移植
    发表于 10-20 16:25

    PID技术_抗扰控制_技术

    PID技术_抗扰控制_技术-2002
    发表于 03-31 17:46 21次下载

    Uber为什么Postgres迁移到MySQL

    导论 Uber的早期架构由一个单体后端应用程序构成,该应用由Python编写,Python使用Postgres以实现数据持久化。那时起,Uber架构已发生巨变,逐步转化为微服务模式和新的数据平台
    发表于 09-30 14:45 4次下载
    Uber为什么<b class='flag-5'>从</b>Postgres迁移到<b class='flag-5'>MySQL</b>

    MySQL数据库:理解MySQL的性能优化、优化查询

    最近一直在为大家更新MySQL相关学习内容,可能有朋友不懂MySQL的重要性。在程序,语言,架构更新换代频繁的今天,MySQL 恐怕是大家使用最多的存储数据库了。由于MySQL的优化范
    的头像 发表于 07-02 17:18 3069次阅读
    <b class='flag-5'>MySQL</b>数据库:理解<b class='flag-5'>MySQL</b>的性能优化、优化查询

    何处理化料机轴表面磨损

    何处理化料机轴表面磨损
    发表于 01-17 10:45 5次下载

    何处理轴表面磨损造成的伤害

    何处理轴表面磨损造成的伤害
    发表于 02-15 16:03 1次下载

    MySQLClickHouse实时复制与实现

    ClickHouse 可以挂载为 MySQL 的一个库 ,先全量再增量的实时同步 MySQL 数据,这个功能可以说是今年最亮眼、最刚需的功能,基于它我们可以轻松的打造一套企业级解决方案,让 OLTP 和 OLAP 的融合从此不
    的头像 发表于 01-03 10:54 759次阅读

    线上MySQL增id用尽怎么办?

    MySQL增id都定义了初始值,然后不断加步长。虽然自然数没有上限,但定义了表示这个数的字节长度,计算机存储就有上限。
    的头像 发表于 05-22 10:23 491次阅读
    线上<b class='flag-5'>MySQL</b>的<b class='flag-5'>自</b>增id用尽怎么办?

    调试TrustZone时,如何处理HardFault?

    调试TrustZone时,如何处理HardFault?
    的头像 发表于 09-27 16:33 649次阅读
    调试TrustZone时,如<b class='flag-5'>何处理</b>HardFault?

    什么是串扰?该如何处理它?

    什么是串扰?该如何处理它?
    的头像 发表于 12-05 16:39 799次阅读
    什么是串扰?该如<b class='flag-5'>何处理</b>它?

    何处理MOS管小电流发热?

    何处理MOS管小电流发热?
    的头像 发表于 12-07 15:13 584次阅读
    如<b class='flag-5'>何处理</b>MOS管小电流发热?