前言

IvorySQL是一款基于PostgreSQL研发的,具备Oracle兼容个性的数据库,所以本文次要介绍IvorySQL中Oracle兼容个性具体案例。

一、零碎参数

(一)compatible_mode

compatible_mode是IvorySQL目前所提供的零碎参数,次要用于示意以后数据库实例兼容模式,其取值有两个,一个是Oracle,一个是Postgres,咱们能够在应用时依据本人须要来进行切换(全局或者会话级)。

在全局设定时,咱们须要initdb的时候指定-c 来确定以后数据库实例兼容模式;

./initdb -D ../data -U ivorysql -c oracle

在以后数据库实例的postgresql.conf文件中,能够看到以后的兼容模式,如下:

# default configuration for compatibility modecompatible_mode = oracle  # postgres, oracle

会话级设定兼容模式,如下:

ivorysql=# set compatible_mode = oracle;SETivorysql=# select 1 from dual; ?column?----------        1(1 row)ivorysql=# set compatible_mode = postgres;SETivorysql=# select 1 from dual;ERROR:  relation "dual" does not existLINE 1: select 1 from dual;

通过上述后果能够看到以后兼容模式切换前后对伪表的操作后果。

(二)nls_length_semantics

用于指定会话中创立的数据库对象中的VARCHAR2和CHAR表列、用户定义的对象属性和PL/SQL变量的默认长度语义。

注:NCHAR、NVARCHAR2、CLOB和NCLOB列始终基于字符。

以下以创立带有varchar2和nvarchar2列的表来进行介绍:

Varchar2

ivorysql=# create table test(a varchar2(5));CREATE TABLEivorysql=# SET NLS_LENGTH_SEMANTICS TO CHAR;SETivorysql=# SHOW NLS_LENGTH_SEMANTICS; nls_length_semantics---------------------- char(1 row)ivorysql=# insert into test values ('开源数据库');INSERT 0 1ivorysql=# SET NLS_LENGTH_SEMANTICS TO byte;SETivorysql=# insert into test values ('开源数据库');ERROR:  value too long for type varchar2(5 byte)ivorysql=# insert into test values ('ivory');INSERT 0 1

Nvarchar2

ivorysql=# create table test(a nvarchar2(5));CREATE TABLEivorysql=# SET NLS_LENGTH_SEMANTICS TO CHAR;SETivorysql=# insert into test values ('开源数据库');INSERT 0 1ivorysql=# SET NLS_LENGTH_SEMANTICS TO byte;SETivorysql=# insert into test values ('开源数据库');INSERT 0 1ivorysql=# insert into test values ('开源数据库1');ERROR:  input value too long for type nvarchar2(5)ivorysql=# insert into test values ('ivory');INSERT 0 1ivorysql=# insert into test values ('ivorys');ERROR:  input value too long for type nvarchar2(5)

从上述后果来看,设置成char或者byte,对于varchar2列是无效;则对于nvarchar2列来说,则只反对char,这与Oracle原参数设置成果是统一的。

二、高级个性

在以后IvorySQL的版本中,相对来说高级个性包含了档次查问以及包,档次查问次要反对通过SQL来进行汇总统计和剖析应用;包则是兼容个性的一个相对来说高级根底个性,次要是因为零碎包开发都是须要该个性来进行实现的。

(一)档次查问

层级查问是一种容许对分层数据进行操作的 SQL 语句。
1.语法

{ CONNECT BY [ NOCYCLE ] [PRIOR] condition [AND [PRIOR] condition]... [ START WITH condition ] | START WITH condition CONNECT BY [ NOCYCLE ] [PRIOR] condition [AND [PRIOR] condition]...}

本示例演示如何调用档次查问相干语法,结构查问后果。

创立一张测试数据表并插入数据:

CREATE TABLE employees(    employee_id integer,     name varchar(25), manager_id integer);insert into employees values(101, 'Kochhar', 100);insert into employees values(108, 'Greenberg', 101);insert into employees values(109, 'Faviet', 108);insert into employees values(110, 'Chen', 108);insert into employees values(111, 'Sciarra', 108);insert into employees values(112, 'Urman', 108);

--根本查问

postgres=# SELECT name, employee_id, manager_id, LEVELpostgres-# FROM employees START WITH employee_id = 101postgres-# CONNECT BY PRIOR employee_id = manager_id; name    | employee_id | manager_id | LEVEL-----------+-------------+------------+------- Kochhar   |         101 |        100 |     1 Greenberg |         108 |        101 |     2 Faviet    |         109 |        108 |     3 Chen      |         110 |        108 |     3 Sciarra   |         111 |        108 |     3 Urman     |         112 |        108 |     3(6 rows)

--SYS_CONNECT_BY_PATH

postgres=# SELECT name "Employee", SYS_CONNECT_BY_PATH(name, '/') "Path"postgres-# FROM employeespostgres-# START WITH name = 'Kochhar'postgres-# CONNECT BY PRIOR employee_id = manager_id; Employee  |            Path-----------+---------------------------- Kochhar   | /Kochhar Greenberg | /Kochhar/Greenberg Faviet    | /Kochhar/Greenberg/Faviet Chen      | /Kochhar/Greenberg/Chen Sciarra   | /Kochhar/Greenberg/Sciarra Urman     | /Kochhar/Greenberg/Urman(6 rows)

--order by

postgres=# SELECT name, CONNECT_BY_ROOT employee_id as "Manager", SYS_CONNECT_BY_PATH(name, '/') "Path"postgres-# From Employees START WITH manager_id is not nullpostgres-# CONNECT BY PRIOR employee_id = manager_idpostgres-# ORDER BY employee_id, manager_id;   name    | Manager |            Path-----------+---------+---------------------------- Kochhar   |     101 | /Kochhar Greenberg |     101 | /Kochhar/Greenberg Greenberg |     108 | /Greenberg Faviet    |     108 | /Greenberg/Faviet Faviet    |     109 | /Faviet Faviet    |     108 | /Kochhar/Greenberg/Faviet Chen      |     108 | /Kochhar/Greenberg/Chen Chen      |     110 | /Chen Chen      |     108 | /Greenberg/Chen Sciarra   |     108 | /Kochhar/Greenberg/Sciarra Sciarra   |     111 | /Sciarra Sciarra   |     108 | /Greenberg/Sciarra Urman     |     112 | /Urman Urman     |     108 | /Greenberg/Urman Urman     |     108 | /Kochhar/Greenberg/Urman(15 rows)

--CONNECT_BY_ROOT和SYS_CONNECT_BY_PATH

postgres=# SELECT employee_id, manager_id, name, CONNECT_BY_ROOT employee_id as "Manager", SYS_CONNECT_BY_PATH(name, '/') "Path"postgres-# FROM employeespostgres-# START WITH manager_id is not nullpostgres-# CONNECT BY PRIOR employee_id = manager_idpostgres-# order by employee_id, manager_id; employee_id | manager_id |   name    | Manager |            Path-------------+------------+-----------+---------+----------------------------         101 |        100 | Kochhar   |     101 | /Kochhar         108 |        101 | Greenberg |     101 | /Kochhar/Greenberg         108 |        101 | Greenberg |     108 | /Greenberg         109 |        108 | Faviet    |     108 | /Greenberg/Faviet         109 |        108 | Faviet    |     109 | /Faviet         109 |        108 | Faviet    |     108 | /Kochhar/Greenberg/Faviet         110 |        108 | Chen      |     108 | /Kochhar/Greenberg/Chen         110 |        108 | Chen      |     110 | /Chen         110 |        108 | Chen      |     108 | /Greenberg/Chen         111 |        108 | Sciarra   |     108 | /Kochhar/Greenberg/Sciarra         111 |        108 | Sciarra   |     111 | /Sciarra         111 |        108 | Sciarra   |     108 | /Greenberg/Sciarra         112 |        108 | Urman     |     112 | /Urman         112 |        108 | Urman     |     108 | /Greenberg/Urman         112 |        108 | Urman     |     108 | /Kochhar/Greenberg/Urman(15 rows)

目前此性能有以下限度:

  • 附加列可用于大多数表达式,如函数调用、CASE 语句和通用表达式,但有局部不受反对的列,如 ROW、TYPECAST、COLLATE、GROUPING 子句等。
  • 两个或多个列雷同的状况下,可能须要输入列名,例如:

SELECT CONNECT_BY_ROOT col AS "col1", CONNECT_BY_ROOT col AS "col2"。

  • 不反对间接运算符或“*”。
  • 不反对循环检测(Loop detection)。

目前来看,包含伪列、函数等操作的反对还须要增强,心愿后续该性能能够更加丰盛。

(二)包

包简略来说就是一个对象或一组对象打包在一起。将过程、函数、变量、游标、用户定义的记录类型和援用记录的逻辑分组汇合打包在本人外部,在申明包和包体定义后(架构和内容)就能够进行调用。

示例1演示如何创立包和包体,并且进行包内函数调用,脚本如下:

--申明包

postgres=# create or replace package pkg ispostgres$#   x int;postgres$#postgres$#   function tfunc(x int) return int;postgres$# end;postgres$# /CREATE PACKAGE

--申明包体

postgres=# create or replace package body pkg ispostgres$#postgres$#   function tfunc(x int) return int aspostgres$#   beginpostgres$# return x;postgres$#   end;postgres$# end;postgres$# /CREATE PACKAGE BODY

--能够通过零碎表查看包内成员

postgres=# select proname, proargtypes from pg_proc p, pg_package pk where pronamespace=pk.oid and pkgname='pkg' order by proname; proname | proargtypes---------+------------- pkg     | tfunc   | 23(2 rows)

--调用包内函数

postgres=# select pkg.tfunc(10); tfunc-------    10(1 row)

示例2演示包内函数和存储过程重载如下:

--创立包定义

postgres=# create or replace package pkgpostgres-# ispostgres$#postgres$#   function tfunc return int;postgres$#postgres$#   procedure tpro;postgres$#postgres$#   function tfunc(x int,y int) return int;postgres$#   procedure tpro(x int);postgres$# end;postgres$# /CREATE PACKAGE

--创立包体

postgres=# create or replace package body pkgpostgres-# ispostgres$#   function tfunc return intpostgres$#   aspostgres$#   beginpostgres$#    return 0;postgres$#   end;postgres$#postgres$#   procedure tpropostgres$#   aspostgres$#   pvar int;postgres$#   beginpostgres$#    pvar:=10;postgres$#   end;postgres$#postgres$#   function tfunc(x int,y int) return intpostgres$#   aspostgres$#   beginpostgres$#    return (x+y);postgres$#   end;postgres$#postgres$#   procedure tpro(x int)postgres$#   aspostgres$#   y int;postgres$#   beginpostgres$#    y := x;postgres$#   end;postgres$# end;postgres$# /CREATE PACKAGE BODY

--执行函数调用

select pkg.tfunc();select pkg.tfunc(1,2);

三、总结

上文介绍并演示了IvorySQL的几个兼容个性,作为目前惟一基于PG开源的Oracle兼容数据库来说,尽管具体性能与原生Oracle还有十分大的差距,然而毕竟仍在起步阶段,心愿将来IvorySQL能减少更多的兼容个性。
另外,在相干配套工具方面,包含管理工具、数据迁徙、复制等,以及在云相干利用方面提供更多的可用产品。

对于IvorySQL

IvorySQL是由瀚高开发,基于PostgreSQL的一款具备弱小Oracle兼容能力的开源数据库。紧跟PG社区,疾速进行版本迭代,放弃与最新版本PostgreSQL数据库内核同步,并反对丰盛的PostgreSQL周边工具和扩大。

IvorySQL致力于创立容纳和激情的社区,保持凋谢,自在,共享的精力,放弃专一、专业性。

官网网址:
https://www.ivorysql.org/zh-cn/
社区仓库:
https://github.com/IvorySQL/I...
IvorySQL社区欢送并赞叹所有类型的奉献,期待您的退出!
还有,别忘了在GitHub给咱们一个 ⭐奥~