7.2.?支持特性

7.2.1. 数据类型
7.2.2. 系统视图和dual表
7.2.3. 函数
7.2.4. 操作符
7.2.5. 支持的包

orafce支持了Oracle的一千多个函数、十几个系统表、部分数据类型、十几个常用包、部分操作符等。

orafce的实现都是基于函数、视图来实现的。所以如果要做语法兼容,orafce的做法是无法实现的。因为UXDB的语法分析在调用视图和函数之前。必须要在语法分析之前切入hook才能使用extension的实现做语法兼容性。因此,目前的orafce对于Oracle的兼容并不是很完善,契合度不是很高。

7.2.1.?数据类型

支持三种数据类型:oracle.date、varchar2和nvarchar2。

表?7.1.?数据类型

类型名称对应UXDB类型Oracle类型
varchar2varcharvarchar2
nvarchar2varcharnvarchar2
oracle.datetimestamp(0)date

uxdb=# create table ora_ux(col1 varchar2,col2 nvarchar2,col3 oracle.date);
CREATE TABLE
uxdb=# insert into ora_ux values ('oracle','uxdb',now());
INSERT 0 1
uxdb=# select * from ora_ux;
  col1  | col2 |        col3         
--------+------+---------------------
 oracle | uxdb | 2019-07-10 17:09:16
(1 row)

注意

由于UXDB的date类型只有日期没有时间,但Oracle的date类型包含日期和时间,所以orafce将Oracle的date类型用UXDB的timestamp(0)表示,且为了避免与UXDB原生的date类型冲突,使用时需要用oracle.date。

7.2.2.?系统视图和dual表

orafce包含了一些Oracle兼容的系统视图和dual表。

由于存在大量的Oracle用户使用dual表,因此UXDB中创建了dual表,是通过视图来实现的。

表?7.2.?系统视图和dual表

名称Oracle中该表的内容orafce中的内容
dual虚拟表,用来构成select的语法规则虚拟表,和Oracle一样
oracle.user_tab_columns保存当前用户的表、视图和Clusters中的列等信息,用于oracle获取表结构缺少默认值、自增列相关的信息
oracle.user_tables保存当前用户的关系表,包含表的基本信息和统计信息只有表名,其他都没有
oracle.user_cons_columnsowner、约束名、表名、列名、position缺少owner、position
oracle.user_constraints保存当前用户拥有的所有约束的定义只有约束名、类型、表名、索引名;缺少搜索条件、owner、删除条件、状态等等
oracle.product_component_version保存组件的版本、名称、状态信息同Oracle一样
oracle.user_objects保存当前用户拥有的所有对象缺少时间戳、标记等信息
oracle.user_procedures保存所有函数和过程及其相关属性只有对象名称
oracle.user_source保存当前用户拥有的存储对象的文本源同Oracle一样
oracle.user_views保存当前用户拥有的视图信息只有视图名称和owner,其他都没有
oracle.user_ind_columns保存当前用户拥有的索引的列只有表名、索引名、列名,其他都没有
oracle.dba_segments保存记录各个段的详细信息,包括当前对象所拥有的分配给所有段的存储空间只有owner、段名、段类型、所属表空间、头文件ID、blockID、段大小、块大小

uxdb=# \dv oracle.*
                 List of relations
 Schema |           Name            | Type | Owner 
--------+---------------------------+------+-------
 oracle | dba_segments              | view | uxdb
 oracle | product_component_version | view | uxdb
 oracle | user_cons_columns         | view | uxdb
 oracle | user_constraints          | view | uxdb
 oracle | user_ind_columns          | view | uxdb
 oracle | user_objects              | view | uxdb
 oracle | user_procedures           | view | uxdb
 oracle | user_source               | view | uxdb
 oracle | user_tab_columns          | view | uxdb
 oracle | user_tables               | view | uxdb
 oracle | user_views                | view | uxdb
(11 rows)
uxdb=# \dv
List of relations
 Schema | Name | Type | Owner 
--------+------+------+-------
 public | dual | view | uxdb
(1 row)

7.2.3.?函数

UXDB中,系统表ux_proc用来保存函数或存储过程的信息,对比安装orafce前后字典表中的数据行数,可以知道orafce创建了大约400多个函数。

uxdb=# select count(*) from ux_proc ;
 count 
-------
  2894
(1 row)
uxdb=# create extension orafce;
CREATE EXTENSION
uxdb=# select count(*) from ux_proc ;
 count 
-------
  3384
(1 row)
  1. 字符串处理:填充和截取

    字符串填充

    uxdb=# select oracle.rpad('abcd',8,'tx');
     rpad   
    ----------
     abcdtxtx
    (1 row)
    uxdb=# select oracle.lpad('abcd',8,'tx');
     lpad   
    ----------
     txtxabcd
    (1 row)

    字符串截取

    uxdb=# select oracle.substr('adbc',2,2);
     substr 
    --------
     db
    (1 row)
    uxdb=# SELECT btrim('abcd','cd') FROM dual;
     btrim 
    -------
     ab
    (1 row
  2. 获取数据库信息

    返回服务器时间

    uxdb=# select oracle.sysdate() from dual;
            sysdate       
    ---------------------
     2019-07-11 07:06:48
    (1 row)

    返回服务器时区

    uxdb=# select oracle.dbtimezone() from dual;
     dbtimezone 
    ------------
     GMT
    (1 row)

    返回当前会话的时区

    uxdb=# select oracle.sessiontimezone() from dual;
     sessiontimezone 
    -----------------
     PRC
    (1 row)

    获取数据库版本

    uxdb=# select oracle.get_major_version();
     get_major_version 
    -------------------
     UXsinoDB 10.0
    (1 row)
  3. 日期处理:日期转换、加减、日期范围区间判断

    返回日期加n个月

    uxdb=# select oracle.add_months(oracle.date'2019-05-21 10:12:12',1) from dual;
         add_months      
    ---------------------
     2019-06-21 10:12:12
    (1 row)

    返回日期值月的最后一天

    uxdb=# select oracle.last_day(oracle.date '2019-05-21 11:12:12') from dual;
     last_day       
    ---------------------
     2019-05-31 11:12:12
    (1 row)

    返回大于日期值的第一个星期日期(可用1-7表示)

    uxdb=# select oracle.next_day(oracle.date '2019-05-21 10:12:12', 'monday') from dual;
          next_day       
    ---------------------
     2019-05-27 10:12:12
    (1 row)

    返回时date1和date2之间的月数,如果不是整月,按每月31天算

    uxdb=# select oracle.months_between(oracle.date '2019-06-21 10:00:00', oracle.date '2019-05-21 10:21:11') from dual;
     months_between 
    ----------------
                  1
    (1 row)
  4. 类型转换:字符串、日期、数值之间转换

    日期转换为字符串

    uxdb=# select oracle.to_char(to_date('14-Jan-19 11:44:49+05:30'));
       to_char       
    ---------------------
     2019-01-14 11:44:49
    (1 row)

    字符串转换为日期

    uxdb=# select oracle.to_date('05/16/19 04:12:12') from dual;
      to_date       
    ---------------------
     2019-05-16 04:12:12
    (1 row)

7.2.4.?操作符

orafce重载了+ - 操作符,用于支持oracle.date类型与smallint、integer类型的加减。

uxdb=# select  ux_catalog.to_date('2019-07-02 10:08:55','YYYY-MM-DD HH:MI:SS') + 9::smallint;
  ?column?  
------------
 2019-07-11
(1 row))
uxdb=# select  ux_catalog.to_date('2019-07-02 10:08:55','YYYY-MM-DD HH:MI:SS') - 9::integer;
  ?column?  
------------
 2019-06-23
(1 row)
uxdb=# select oracle.to_date('2019-07-17 11:10:15', 'yyyy-mm-dd hh24:mi:ss') - oracle.to_date('2019-02-01 10:00:00', 'yyyy-mm-dd hh24:mi:ss');
     ?column?      
-------------------
 166 days 01:10:15
(1 row)

7.2.5.?支持的包

在UXDB里用schema+函数的形式来实现Oracle兼容包。

uxdb=# \dn
 List of schemas
     Name     | Owner 
--------------+-------
 dbms_alert   | uxdb
 dbms_assert  | uxdb
 dbms_output  | uxdb
 dbms_pipe    | uxdb
 dbms_random  | uxdb
 dbms_utility | uxdb
 oracle       | uxdb
 plunit       | uxdb
 plvchr       | uxdb
 plvdate      | uxdb
 plvlex       | uxdb
 plvstr       | uxdb
 plvsubst     | uxdb
 public       | uxdb
 utl_file     | uxdb
(15 rows)

查看包,例如dbms_output包:

uxdb=# \df dbms_output.*
          List of functions
   Schema    |     Name     | Result data type |           Argument data types            |  Type  
-------------+--------------+------------------+------------------------------------------+--------
 dbms_output | disable      | void             |                                          | normal
 dbms_output | enable       | void             |                                          | normal
 dbms_output | enable       | void             | buffer_size integer                      | normal
 dbms_output | get_line     | record           | OUT line text, OUT status integer        | normal
 dbms_output | get_lines    | record           | OUT lines text[], INOUT numlines integer | normal
 dbms_output | new_line     | void             |                                          | normal
 dbms_output | put          | void             | a text                                   | normal
 dbms_output | put_line     | void             | a text                                   | normal
 dbms_output | serveroutput | void             | boolean                                  | normal
(9 rows)
  1. dbms_output

    UXDB通过raise notice向客户端发送信息。

    --打开serveroutput
    select dbms_output.serveroutput('t');
    --打开dbms_output生效,默认打开
    select dbms_output.enable();
    --写入buffer但不输出
    select dbms_output.put('a');
    --写入buffer但不输出
    select dbms_output.put('b');
    --输出并换行
    select dbms_output.put_line('c');
  2. utl_file

    允许UXSQL prgrams从服务器读写任何文件。每个会话最多可以打开10个文件,最大行大小为32K。

  3. dbms_pipe

    用于在不同会话之间进行通信。可以建立公有和私有管道,所有用户都可以访问公有管道,只有建立管道的用户可以访问私有管道。

    表?7.3.?dbms_pipe功能表

    功能名称功能描述
    pack_message用于将消息写入到本地消息缓冲区
    send_message用于将本地消息缓冲区中的内容发送到管道
    receive_message用于接收管道消息
    next_item_type用于确定本地消息缓冲区下一项的数据类型
    如果该返回0,则表示管道没有任何消息
    如果返回6,则表示下一项的数据类型为number
    如果返回9,则表示下一项的数据类型为varchar2
    如果返回11,则表示下一项的数据类型为rowid
    如果返回12,则表示下一项的数据类型为date
    如果返回13,则表示下一项的数据类型为timestamp
    如果返回23,则表示下一项的数据类型为bytea(Oracle中是raw)
    unpack_message用于将消息缓冲区的内容写入到变量中
    remove_pipe用于删除已经建立的管道
    puger用于清除管道中的内容
    reset_buffer用于复位管道缓冲区
    unique_session_name用于为特定会话返回惟一名称,且名称的最长度为30字节

    -- Session A
    --创建一个公用管道
    select dbms_pipe.create_pipe('my_pipe',10,true); 
    --将消息写入到本地消息缓冲区
    select dbms_pipe.pack_message('uxsino');
    --将消息写入到本地消息缓冲区
    select dbms_pipe.pack_message('anything is else');
    --本地消息发送到管道
    select dbms_pipe.send_message('my_pipe'); 
    --查看管道列表
    select * from dbms_pipe.db_pipes; 
    -- Session B
    --接收管道消息
    select dbms_pipe.receive_message('my_pipe');
    --确定本地消息缓冲区下一项的数据类型
    select dbms_pipe.next_item_type();
    --将消息缓冲区的内容写入到变量中
    select dbms_pipe.unpack_message_text();
    select dbms_pipe.next_item_type(); 
    --删除已经建立的管道
    select dbms_pipe.remove_pipe('my_pipe');

    注意

    dbms_pipe和Oracle中的不同之处:

    1.管道的限制不是以字节为单位的,而是以管道中的元素为单位的。

    2.发送消息可以不用等待。

    3.可以发送空消息。

    4.next_item_type有timestamp类型,返回值是13。

    5.UXDB无法识别出raw类型,用bytea代替。

  4. dbms_alert

    进程间通信的一种方法。用于生成并传递数据库预警信息。

    表?7.4.?dbms_alert功能表

    功能名称功能描述
    dbms_alter.register用于注册预警事件
    dbms_alter.remove用于删除会话不需要的预警事件
    dbms_alter.removeall用于删除当前会话所有已注册的预警事件
    dbms_alter.signal用于指定预警事件所对应的预警消息
    dbms_alter.waitany用于等待当前会话的任何预警事件,并且在预警事件发生时输出相应信息.在执行该过程之前,会隐含地发出COMMIT( 注:status用于返回状态值,返回0表示发生了预警事件,返回1表示超时;timeout用于设置预警事件的超时时间)
    dbms_alter.waitone用于等待当前会话的特定预警事件,并且在发生预警事件时输出预警消息

    -- Session A
    --注册预警事件
    select dbms_alert.register('uxsino');
    --等待预警事件,超时时间是600s
    select * from dbms_alert.waitany(600);
    -- Session A
    --在超时时间内执行,则sessionA返回状态为0,否则返回为1
    select dbms_alert.signal('uxsino','Nice day');
  5. PLVdate

    包含了一些工作日的计算,默认配置适用于欧洲国家。

    表?7.5.?PLVdate功能表

    功能名称功能描述
    plvdate.add_bizdays(day date, days int) date返回date+n个工作日的日期
    plvdate.nearest_bizday(day date) date返回给定日期最近的工作日或休息日
    plvdate.next_bizday(day date) date返回给定日期下一个的工作日或休息日
    plvdate.bizdays_between(day1 date, day2 date) int两个日期之间的工作日数
    plvdate.prev_bizday(day date) date返回给定日期前一个的工作日或休息日
    plvdate.isbizday(date) bool确定是否是工作日
    plvdate.set_nonbizday(dow varchar)将一周中的某一天设为非工作日
    plvdate.unset_nonbizday(dow varchar)将一周中的某一天设置为工作日
    plvdate.set_nonbizday(day date)将当天设为非工作日
    plvdate.unset_nonbizday(day date)将当天设为工作日
    plvdate.set_nonbizday(day date, repeat bool)将给定日期设定为工作日,如果为真,则每年的这个日期都是工作日
    plvdate.unset_nonbizday(day date, repeat bool)将给定日期设定为非工作日,如果为真,则每年的这个日期都是非工作日
    plvdate.use_easter()设置复活节和复活节后的一周为放假日
    plvdate.using_easter() bool如果是复活节则返回true
    plvdate.use_great_friday()复活节后的周五设置为放假日
    plvdate.using_easter() bool如果复活节是周五,则返回真
    plvdate.include_start()在bizdays_between计算中包含开始日期
    plvdate.noinclude_start()在bizdays_between计算中不包含开始日期
    plvdate.default_holidays(varchar)加载默认配置

    配置只包含所有区域的公共假日。可以使用set_nonbizday自定义区域假日。

  6. PLVstr and PLVchr

    包含一些字符串和字符相关函数。支持正向偏移和负向偏移。

    表?7.6.?PLVstr and PLVchr功能表

    功能名称功能描述
    plvstr.normalize(str text)格式化字符串,去除字符串前面多余的空格
    plvstr.is_prefix(str text, prefix text, cs bool)str的前缀是prefix,则返回真
    plvstr.is_prefix(str text, prefix text)str的前缀是prefix,则返回真
    plvstr.is_prefix(str int, prefix int)str的前缀是prefix,则返回真
    plvstr.is_prefix(str bigint, prefix bigint)str的前缀是prefix,则返回真
    plvstr.substr(str text, start int, len int)返回str字符串中从第start位开始的len位字符
    plvstr.substr(str text, start int)返回str字符串中从第start位开始到结束的字符
    plvstr.instr(str text, patt text, start int, nth int)字符串检索
    plvstr.instr(str text, patt text, start int)字符串检索
    plvstr.instr(str text, patt text)字符串检索
    plvstr.lpart(str text, div text, start int, nth int, all_if_notfound bool)all_if_notfound为t,则返回全部;all_if_notfound为f,则返回空;all_if_notfound不定义,则从第start开始,往后nth个字符串中包含div,则返回nth左边的字符
    plvstr.lpart(str text, div text, start int, nth int)从第start开始,往后nth个字符串中包含div,则返回nth左边的字符
    plvstr.lpart(str text, div text, start int)从第start开始,往后的字符串中包含div,则返回start左边的字符
    plvstr.lpart(str text, div text)返回str中div左边的字符
    plvstr.rpart(str text, div text, start int, nth int, all_if_notfound bool)all_if_notfound为t,则返回全部;all_if_notfound为f,则返回空;all_if_notfound不定义,则从第start开始,往后nth个字符串中包含div,则返回nth右边的字符
    plvstr.rpart(str text, div text, start int, nth int)从第start开始,往后nth个字符串中包含div,则返回nth右边的字符
    plvstr.rpart(str text, div text, start int)从第start开始,往后的字符串中包含div,则返回nth右边的字符
    plvstr.rpart(str text, div text)返回str中div左边的字符
    plvstr.lstrip(str text, substr text, num int)从str最左边开始删除连续的小于等于num个substr字符
    plvstr.lstrip(str text, substr text)从str最左边开始删除一个substr字符
    plvstr.rstrip(str text, substr text, num int)从str最右边开始删除连续的小于等于num个substr字符
    plvstr.rstrip(str text, substr text)从str最右边开始删除一个substr字符
    plvstr.rvrs(str text, start int, end int)返回反转的str中start到end的字符串
    plvstr.rvrs(str text, start int)返回反转的str中start开始的字符串
    plvstr.rvrs(str text)反转str字符串
    plvstr.left(str text, n int)返回第一个到第n个字符串
    plvstr.right(str text, n int)返回第n个到最后一个字符串
    plvstr.swap(str text, replace text, start int, lengh int)用replace替换str中start开始lengh长度的字符串
    plvstr.swap(str text, replace text)用replace替换str中开头的字符串
    plvstr.betwn(str text, start int, _end int, inclusive bool)找到开始和结束位置之间的子字符串
    plvstr.betwn(str text, start text, _end text, startnth int, endnth int, inclusive bool, gotoend bool)找到开始和结束位置之间的子字符串
    plvstr.betwn(str text, start text, _end text)找到开始和结束位置之间的子字符串
    plvstr.betwn(str text, start text, _end text, startnth int, endnth int)找到开始和结束位置之间的子字符串
    plvchr.nth(str text, n int)返回字符串中的第n个字符
    plvchr.first(str text)返回字符串中的第一个字符
    plvchr.last(str text)返回字符串中的最后一个字符
    plvchr.is_blank(c int)是否为空
    plvchr.is_blank(c text)是否为空
    plvchr.is_digit(c int)是否为十进制数字
    plvchr.is_digit(c text)是否为十进制数字
    plvchr.is_quote(c int)是否为特殊字符
    plvchr.is_quote(c text)是否为特殊字符
    plvchr.is_other(c int)--
    plvchr.is_other(c text)--
    plvchr.is_letter(c int)是否是字母
    plvchr.is_letter(c text)是否是字母
    plvchr.quoted1(str text)引用单引号
    plvchr.quoted2(str text)引用双引号
    plvchr.stripped(str text, char_in text)删除str中的char_in

    -- ab
    select plvstr.left('abcdef',2);
    -- abcd
    select plvstr.left('abcdef',-2);
    -- a
    select plvstr.substr('abcdef',1,1); 
    -- f
    select plvstr.substr('abcdef',-1,1); 
    -- d
    select plvstr.substr('abcde',-2,1); 
  7. DBMS_utility

    表?7.7.?DBMS_utility功能表

    功能名称功能描述
    dbms_utility.format_call_stack()返回带有调用堆栈内容的格式化字符串

    uxdb=# select dbms_utility.format_call_stack();
            format_call_stack        
    ---------------------------------
     ----- PL/uxSQL Call Stack -----+
       object     line  object      +
       handle   number  name        +
    (1 row)
  8. PLVlex

    与Oracle的PLVlex不兼容。

    uxdb=# select * from plvlex.tokens('select * from a.b.c join d ON x=y', true, true);
     pos | token  | code |  class  | separator | mod  
    -----+--------+------+---------+-----------+------
       0 | select |  597 | KEYWORD |           | 
       7 | *      |   42 | OTHERS  |           | self
       9 | from   |  417 | KEYWORD |           | 
      14 | a.b.c  |      | IDENT   |           | 
      20 | join   |  464 | KEYWORD |           | 
      25 | d      |      | IDENT   |           | 
      27 | on     |  521 | KEYWORD |           | 
      30 | x      |      | IDENT   |           | 
      31 | =      |   61 | OTHERS  |           | self
      32 | y      |      | IDENT   |           | 
    (10 rows)
  9. DBMS_ASSERT

    保护用户输入不受SQL注入的影响。

    表?7.8.?DBMS_ASSERT功能表

    功能名称功能描述
    dbms_assert.enquote_literal(varchar) varchar添加前引号和后引号,验证所有单引号都与相邻的单引号配对
    dbms_assert.enquote_name(varchar [, boolean]) varchar大写的字符串用双引号标记
    dbms_assert.noop(varchar) varchar 返回值而不进行任何检查
    dbms_assert.qualified_sql_name(varchar) varchar此函数验证输入字符串是否是限定的SQL名称
    dbms_assert.schema_name(varchar) varchar函数验证输入字符串是否是现有schema名
    dbms_assert.simple_sql_name(varchar) varchar这个函数验证输入字符串是否是简单的SQL名称
    dbms_assert.object_name(varchar) varchar验证输入字符串是否为现有SQL对象的限定SQL标识符

  10. PLUnit

    包含一些断言函数。

    表?7.9.?PLUnit功能表

    功能名称功能描述
    plunit.assert_true(bool [, varchar])断言条件为true
    plunit.assert_false(bool [, varchar])断言条件为false
    plunit.assert_null(anyelement [, varchar])断言实际值为空
    plunit.assert_not_null(anyelement [, varchar])断言实际值不为空
    plunit.assert_equals(anyelement, anyelement [, double precision] [, varchar])断言期望和实际是相等的
    plunit.assert_not_equals(anyelement, anyelement [, double precision] [, varchar])断言期望和实际是不相等的
    plunit.fail([varchar])立即失败,并输出消息

  11. DBMS_random

    用于生成随机数。

    表?7.10.?DBMS_random功能表

    功能名称功能描述
    dbms_random.initialize(int)初始化一个种子值的包
    dbms_random.normal()返回标准正态分布中的随机数
    dbms_random.random()返回一个随机值,范围是-2的31次幂到2的31次幂
    dbms_random.seed(int)用于生成一个随机数种子,设置种子的目的是可以重复生成随机数
    dbms_random.seed(text)重置种子值
    dbms_random.string(opt text(1), len int)创建随机字符串
    dbms_random.terminate()终止包 (UXDB中没有任何作用)
    dbms_random.value()在[0.0 - 1.0)之间返回一个随机值
    dbms_random.value(low double precision, high double precision)在[low - high)之间返回一个随机值

XML 地图 | Sitemap 地图