IvorySQL 3.4:如何实现兼容Oracle风格的序列功能?

1

什么是序列?

一个序列是一个数据库对象,与表和视图类似,它表示可以由全局数据库命名空间中的任何表和视图使用的整数序列。可以使用NEXTVAL和CURRVAL访问序列值。序列可以是升序或降序。

2

Oracle的序列相比PG多了什么?

  • 支持CACHE/NOCACHE、SCALE、SESSION、GLOBAL特性;

  • 支持NEXTVAL和CURRVAL伪列实现;

  • 支持三个序列视图,ALL_SEQUENCES、DBA_SEQUENCES、USER_SEQUENCES;

3

3.4 的设计概述

为了兼容oracle中sequence的特性与功能,我们主要处理工作有以下几个方面:

  • 语法修改,兼容oracle序列的部分语法。

  • 功能实现,实现兼容oracle的部分序列功能。

  • 序列调用的兼容,支持NEXTVAL和CURRVAL伪列使用序列值。

  • 序列相关视图的创建以及序列的备份相关内容。

4

3.4 具体特性

4.1 CACHE/NOCACHE兼容
  • Oracle中CAHCHE只能指定为大于1的值,而PG中可以指定大于0的值。IvorySQL采用了与Oracle相同的做法;

  • 新增关键字NOCACHE,指定NOCACHE时cache值为1,不指定时cache值默认为20;

>>>指定nocache的情况下,cache_size的值为1。
复制代码
create sequence seq_cache nocache;select cache_size from all_sequences where sequence_name='seq_cache'; cache_size ------------          1(1 row)
>> > ********不指定nocache的情况下,cache_size的默认值为20。********​​​​​​​
复制代码
create sequence seq_cache;select cache_size from all_sequences where sequence_name='seq_cache'; cache_size ------------         20(1 row)
  • PG中指定cache大于1时,多个会话之间的序列值会出现间隙,间隙值为cache值,即每个会话缓存了对应序列值,后续会话会从上一个会话缓存后的序列开始计算。而oracle中不同会话中共享一个缓冲序列。IvorySQL沿用了PG的规则;
4.2 SESSION/GLOBAL实现
  • **GLOBAL:**全局序列,会话之间共用一个序列,该选项为默认选项。

  • **SESSION:**每个会话重新登录都会拥有一个起始的序列值,会话之间序列相互不影响。

4.3 RESTART语法功能支持

指定RESTART时,序列值从初始值开始计算,在ALTER中要修改序列的起始值需要和START WITH一起使用以修改序列的起始值。

>> > ********示例:********​​​​​​​
复制代码
CREATE SEQUENCE seq_restart INCREMENT BY 1 START WITH 32 MINVALUE 10 MAXVALUE 50;select seq_restart.nextval from dual; nextval ---------      32(1 row)
alter sequence seq_restart restart;
Restart后序列值从初始值开始计算。select seq_restart.nextval from dual; nextval ---------      10(1 row)
4.4 SCALE序列范围伸缩

SCALE强制将额外的6位数字添加在序列值的前面,组成一个新的序列值,即新的序列值= 6个数字 || 普通序列值。

额外6位数= [system_identifier%100+100] || [session_id%1000]。

这额外的6位数不存储于表中,且默认最大值的情况下加上这6位数值已经超过了bigint的最大值,所以如果指定的最大序列值数大于13位,则报超过序列最大值的错误。

EXTEND和NOEXTEND的区别在于EXTEND会比最大值多6位,而NOEXTEND会跟最大值保持位数相同,设计时需要注意如果maxvalue的最大值位数小于6位时,调用nextval将会报错,或者当nextval获取的NOEXTEND值大于maxvalue时也会报错。

>> > ********示例:********​​​​​​​
复制代码
指定extend 的情况下,额外的6位数字添加在序列值的前面。ivorysql=# CREATE SEQUENCE seq scale extend maxvalue 99999999;CREATE SEQUENCEivorysql=# select seq.nextval from dual;    nextval     ---------------- 17400100000001(1 row)
ivorysql=# DROP SEQUENCE seq;DROP SEQUENCE
指定noextend 的情况下,额外的6位数字嵌在序列值的前部。ivorysql=# CREATE SEQUENCE seq scale noextend maxvalue 99999999;CREATE SEQUENCEivorysql=# select seq.nextval from dual; nextval  ---------- 17400101(1 row)
4.5 NEXTVAL和CURRVAL伪列实现

序列值的引用Oracle使用了NEXTVAL和CURRVAL两个伪列来实现,PG中则使用了NEXTVAL()和CURRVAL()函数来实现,所以在语法分析层当识别到使用了NEXTVAL和CURRVAL伪列引用序列时,将其转换成NEXTVAL()或CURRVAL()函数的调用,以达到实现伪列引用的目的。

4.6 序列相关视图实现

实现ALL_SEQUENCES、DBA_SEQUENCES、USER_SEQUENCES三个视图。

序列的视图实现主要依赖于系统表pg_sequence。序列视图中SHARDED_FLAG和KEEP_VALUE列由于只实现了语法功能,所以这两列的内容为空。

>> > ********示例:********​​​​​​​
复制代码
使用USER_SEQUENCES视图ivorysql=# select min_value, max_value from user_sequences where sequence_name = 'seq'; min_value | max_value -----------+-----------         1 |  99999999(1 row)
使用ALL_SEQUENCES视图ivorysql=# select cache_size from all_sequences where sequence_name='seq'; cache_size ------------         20(1 row)
相关推荐
EQ-雪梨蛋花汤19 分钟前
【工具】在 Visual Studio 中使用 Dotfuscator 对“C# 类库(DLL)或应用程序(EXE)”进行混淆
数据库·ide·visual studio
阿ฅ( ̳• ε • ̳)ฅ1 小时前
C#窗体应用程序连接数据库
开发语言·数据库·c#
光军oi2 小时前
Mysql从入门到精通day5————子查询精讲
android·数据库·mysql
qr9j422334 小时前
Django自带的Admin后台中如何获取当前登录用户
数据库·django·sqlite
cherry52304 小时前
【PostgreSQL】【第4章】PostgreSQL的事务
数据库·postgresql
IT成长日记8 小时前
【MySQL基础】聚合函数从基础使用到高级分组过滤
数据库·mysql·聚合函数
Guarding and trust10 小时前
python系统之综合案例:用python打造智能诗词生成助手
服务器·数据库·python
夜间出没的AGUI10 小时前
SQLiteBrowser 的详细说明,内容结构清晰,涵盖核心功能、使用场景及实用技巧
数据库
不再幻想,脚踏实地11 小时前
MySQL(一)
java·数据库·mysql