• 金仓数据库 KingbaseES V8.3至V8.6迁移最佳实践(2. KingbaseES V8.3和 V8.6 兼容性)


    2. KingbaseES V8.3和 V8.6 兼容性

    本部分包含如下章节:

    • KingbaseES V8.3 和 V8.6 兼容特性概览

    2.1. KingbaseES V8.3 和 V8.6 兼容特性概览

    本章节包含以下内容:

    2.1.1. 兼容性开关

    KingbaseES用户可通过设置相关的数据库兼容开关,部分或全部启用Oracle兼容特性。在实际应用中,用户可采用以下途径设置Oracle兼容开关:

    • 在数据库实例data目录下的kingbase.conf文件中配置

    • 在数据库初始化时设置

    • 在用户会话中设置

    KingbaseES提供了多个Oracle特性兼容开关。在Oracle移植过程中,用户可按需使用这些开关。下表列出KingbaseES提供的Oracle兼容特性开关。

    表 2.1.3 KingbaseES V8.6 和 V8.3 兼容特性开关一览表

    兼容特性开关

    V8R6

    V8.3

    用途说明

    char_default_type

    不支持 ( oracle兼容模 式下默认就是兼 容类型的设置)

    支持

    设置字符串类 型的长度单位(char 或byte),它和 Oracle参数 NLS_LENGTH_SEMATICS 的含义 一致(会话级 参数,缺省值是 char)

    ora_func_style

    不支持 ( oracle兼容模 式下默认就是兼 容类型的设置) 移植时人为去掉设置该参数的sql

    支持

    开关开启时兼容oracle 函数及sequence 序列(会 话级参数,缺省 值是true)

    default_with_oids

    支持

    支持

    开 关开启时,新创 建的表将包含OID 伪列。此 外,如果创建的 表没有OID伪列, 那么这个表也没 有ROWID伪列。如 果创建加密表时 ,必须指定WITH OID。

    ora_input_emptystr_isnull

    支持

    支持

    开 关开启时,系统 将输入的空串当 做NULL处理会 话级参数,缺省 值是true)

    ora_date_style

    支持(KingbaseES 使用此开关设 置date数据类型格式时,需要先 打开ora_style_nls_date_format 开关,且ora_date_style默认时间 格式为' YYYY-MM-DD HH24:mi:ss)

    支持

    开关开启时, date类型的输出 格式兼容oracle date类型输 入格式(会话 级参数,缺省值 是false)

    ora_format_style

    不 支持(可以使用Oracle 模式替代) 移植时人为去掉设置该参数的sql

    支持

    开关开启时 ,格式化输出( to_char,to_time stamp...)兼容 oracle(会话 级参数,缺省值 是false)

    nls_timestamp_format

    不支持

    支持

    开关开启时,time stamp类型to_char 默认输出格式 兼容oracle会 话级参数,缺省 值是YYYY-MM-DD HH:MI:SS)

    nls_length_semantics

    支持

    不支持

    设置字符 串类型的长度单位 (char或byte), 它和Oracle参数 NLS_LENGTH_SEMATICS 的含义一致( 会话级参数, 缺省值是char)

    ora_numop_style

    不支持

    支持

    开关开启时, integers 操作符当做 numeric操作符。

    extra_float_digits

    支 持(默认值为1)

    支 持(默认值为0)

    设置浮点 值显示的位数。

    2.1.2. 模式和对象

    本节内容旨在为移植过程的相关模式修改操作提供参考指南。

    2.1.2.1. 扩展数据类型

    为兼容Oracle的数据类型,KingbaseES扩展了Oracle的NUMBERVARCHAR2CHAR(n)DATE类型。该措施使得移植Oracle的Create Table等DDL语句时,无需任何修改就能直接在KingbaseES环境中运行。

    下面各表对比了KingbaseES和Oracle在各种数据类型上的异同点。

    表 2.1.4 Kingbase V8.6 与 V8.3数值数据类型对比表

    数据类型名

    KingbaseES V8R6

    KingbaseES V8.3

    bool

    不支持bool到text的隐 式转换, (比如like 等操作需要此隐式转 换,可修改应用增加显 示转换绕过此问题.)

    支持bool到int的隐式转换 支持bool到text的隐式转 换.

    time,timetz

    不支持 time和timetz到timestamptz 类型的隐式转换(Oracle 中不存在time和timetz 类型,在不影响Oracle 兼容性的基础上保留 了原型的处理逻辑。可 通过修改应用增加显示 转换来绕过此问题。)

    支 持time和timetz到 timestamptz类型 的隐式转换

    abstime

    不支持

    内部使用的较低精度类型

    reltime

    不支持

    内部使用的较低精度类型

    tinterval

    不支持

    支持

    2.1.2.2. 模式

    V8.6 中search_path中的模式名,需要写成小写;

    例:

    V8.3:

    show search_path ;
       search_path
    -----------------
     "$USER", PUBLIC
    (1 row)
    

    V8.6 :

    show search_path ;
       search_path
    -----------------
     "$user", public
    (1 row)
    

    2.1.2.3. 大小写敏感

    例:

    V8.3:

    show case_sensitive ;
     case_sensitive
    ----------------
     on
    (1 row)
    

    V8.6 :

    show enable_ci ;
     enable_ci
    ----------------
     on
    (1 row)
    

    2.1.2.4. 序列

    V8.3中select * from sequencename可以得到10列信息, V8.6 直接select * from sequencename只有3列,其余列可通过select * FROM all_sequences WHERE sequence_name=UPPER('sequencename')找到。

    例:

    V8.3:

    CREATE SEQUENCE serial START 1;
    select * from serial;
    SEQUENCE_NAME | LAST_VALUE | START_VALUE | INCREMENT_BY |      MAX_VALUE      | MIN_VALUE | CACHE_VALUE | LOG_CNT | I
    S_CYCLED | IS_CALLED
    ---------------+------------+-------------+--------------+---------------------+-----------+-------------+---------+--
    ---------+-----------
     SERIAL        |          1 |           1 |            1 | 9223372036854775807 |         1 |           1 |       0 | f
             | f
    (1 row)
    

    V8.6 :

    CREATE SEQUENCE serial START 1;
    select * from serial ;
     last_value | log_cnt | is_called
    ------------+---------+-----------
              1 |       0 | f
    (1 row)
    select * FROM all_sequences WHERE sequence_name=UPPER('serial');
    sequence_owner | sequence_name | min_value |      max_value      | increment_by | cycle_flag | order_flag | cache_siz
    e | last_number
    ----------------+---------------+-----------+---------------------+--------------+------------+------------+----------
    --+-------------
     abcd           | SERIAL        |         1 | 9223372036854775807 |            1 | f          | t          |
    1 |
    (1 row)
    

    2.1.2.5. 同义词

    V8.6 找同义词时,对于同义词指向的对象,首先依然作为同义词进行递归查找和成环检测,而不是把同义词指向的对象首先按照普通对象查找,这个处理顺序和R3不同。

    2.1.2.6. 分区

    V8.6 分区支持的兼容V8.3,支持分区的alter,支持全局索引,支持interval分区,不支持reference分区

    2.1.2.7. 全局临时表

    V8.3支持本地临时表,不支持全局临时表。

    V8.6 支持本地临时表和全局临时表。

    2.1.2.8. kdb_schedule

    目前龙芯平台没有 kdb_schedule 依赖的系统库libboost_system.so.1.69.0, ES安装程序将这个库放到了Server/lib下,使用kdb_schedule之前需要设置export LD_LIBRARY_PATH 中包含Server/lib。

    export LD_LIBRARY_PATH = $LD_LIBRARY_PATH:/Kingbase_install_dir/Server/lib
    

    2.1.3. SQL语句

    对于大多数常用的Oracle SQL语句,KingbaseES均提供了原生支持。该措施使得Oracle应用程序移植到KingbaseES系统时,通常只需很少的代码变动。

    下面给出KingbaseES中原生支持的Oracle SQL语句。此外,若未做特殊说明,本节示例的代码在KingbaseES和Oracle上均可运行。

    2.1.3.1. 支持CREATE TABLE WITH OIDS语句

    V8.6 支持create table with oids,表中的系统隐含列不再包含OID,但是这样创建的表,包含了一个用户隐含列oid,类型是oid。对于oracle rowid,需要用户创建隐含列rowid,类型是oid。

    例:

    create table tt (a int) with oids;
    ERROR:  syntax error at or near "oids"
    create table tt1 (a int);
    select oid,relname from pg_class where relname = 'tt1';
      oid  | relname
    -------+---------
     16403 | tt1
    (1 row)
    

    2.1.3.2. select * from sequencename 语句

    V8.3中select * from sequencename可以得到10列信息, V8.6 直接select * from sequencename只有3列,其余列可通过select * FROM all_sequences WHERE sequence_name=UPPER('sequencename')找到。

    例:

    V8.3:

    CREATE SEQUENCE serial START 1;select * from serial;
     SEQUENCE_NAME | LAST_VALUE | START_VALUE | INCREMENT_BY |      MAX_VALUE      | MIN_VALUE | CACHE_VALUE | LOG_CNT | IS_CYCLED | IS_CALLED
    ---------------+------------+-------------+--------------+---------------------+-----------+-------------+---------+-----------+-----------
     SERIAL        |          1 |           1 |            1 | 9223372036854775807 |         1 |           1 |       0 | f         | f
    (1 row)
    

    V8.6 :

    CREATE SEQUENCE serial START 1;
    select * from serial ;
     last_value | log_cnt | is_called
    ------------+---------+-----------
              1 |       0 | f
    (1 row)
    select * FROM all_sequences WHERE sequence_name=UPPER('serial');
     sequence_owner | sequence_name | min_value |      max_value      | increment_by | cycle_flag | order_flag | cache_size | last_number | start_value
    ----------------+---------------+-----------+---------------------+--------------+------------+------------+------------+-------------+-------------
     system         | SERIAL        |         1 | 9223372036854775807 |            1 | f          | t          |          1 |             |           1
    

    2.1.3.3. 函数 sys_guid()

    V8.6 默认输出为name类型,如希望输出为bytea类型,需在配置文件中修改guid_default_return_type='bytea'并重启数据库,再通过以下命令实现:

    select alter_sys_guid();
    

    如希望输出为name类型,需在配置文件中修改guid_default_return_type='name'并重启数据库,再通过以下命令实现:

    select alter_sys_guid();
    

    2.1.3.4. 函数 get_byte(bit, int)

    V8.6 不支持get_byte(bit,int)函数

    V8.3:

    test=# SELECT  GET_BYTE(X'164da53ef', 4);
     GET_BYTE
    ----------
          239
    (1 row)
    

    V8.6 :

    test=# SELECT  GET_BYTE(X'164da53ef', 4) ;
    ERROR:  function get_byte(bit, integer) does not exist
    LINE 1: SELECT  GET_BYTE(X'164da53ef', 4) ;
                    ^
    HINT:  No function matches the given name and argument types. You might need to add explicit type casts.
    

    2.1.3.5. 操作符

    相比 V8.3, V8.6 完善了自定义操作符的处理逻辑。对于R3中所限制的自定义操作符中最后一个字符是‘+’或者‘-’的,如果前面包含‘~! @ ^ & ` %’这些字符中的任一字符,则不可以创建自定义操作符。比如在 V8.3中,创建自定义操作符‘~+’,将会报错,而 V8.6 中允许创建, V8.6 中禁用的自定义操作符有10个,包括:"!=+", "!=-", "^=+", "^=-", "||+", "||-", "^+", "^-", " |+", " |-"。这样也是为了尽可能保证处理逻辑与原型一致的基础上,还可以兼容Oracle的操作符。基于上面的处理逻辑,在 V8.3中,比如遇到"%-"这类操作符,实际上是会被当做两个(甚至多个)独立的操作符‘%’和‘-’,而 V8.6 中会认为这是用户自定义的操作符,会当做一个整体。所以在 V8.6 中如果想要将‘%-’操作符当做两个独立的操作符,需要修改应用,在操作符中间插入空格。这一点影响了应用兼容性。

    2.1.4. PL/SQL语言

    对于大多数常用的 Oracle PL/SQL语句,KingbaseES均提供了支持。该措施使得Oracle应用程序移植到KingbaseES系统时,通常只需很少的代码变动。

    下面给出KingbaseES中支持的Oracle PL/SQL语句。此外,若未做特殊说明,本节示例的代码在KingbaseES和Oracle上均可运行。

    2.1.4.1. Internal关键字

    区别:

    V8.3函数创建带internal关键字;REVOKE EXECUTE ON INTERNAL FUNCTION

    V8.6 函数创建不支持internal关键字;REVOKE语句中也不支持INTERNAL关键字

    升级改写方案:

    删除internal关键字

    例2-1

    V8.3:

    CREATE OR REPLACE internal function pr1() return int AS $$
    BEGIN
          return 1;
    END;
    $$language plsql;
    REVOKE EXECUTE ON INTERNAL FUNCTION
    

    V8.6 :

    CREATE OR REPLACE function pr1() return int AS $$
    BEGIN
          return 1;
    END;
    $$language plsql;
    REVOKE EXECUTE ON FUNCTION
    

    2.1.4.2. forall

    区别:

    V8.3支持forall语法及其功能

    V8.6 不支持forall语法和功能

    升级改写方案:

    FORALL基本用法:

    1. 迭代器为lower..higher

    2. 迭代器为indices of collection [between lower and higher]

    3. 迭代器为values of index_collection

    改写规则:

    公有规则:

    1. forall语句中有'save exception'的,忽略掉'save exception';

    2. 将'forall'改为'for';迭代器语句结束加上'loop'; dml语句结尾加上'end loop;';

    三类的各自的规则:

    1类:不做其他额外改动;

    2类:

    首先,

    1. 如果没有between..and

      将迭代器变为 collection.first..collection.last;

    2. 否则将迭代器变为 lower..higher;

    然后,将dml语句包裹在一个if语句中,条件是索引j有效;

    3类:将迭代器变为 index_collection.first..index_collection.last;

    将dml语句包括在一个if语句中,条件是keys(j)有效;

    将dml语句内通过索引引用集合depts(j)改为depts(keys(j));

    仍然存在的问题:

    1. 异常SQL%BULK_EXPCETIONS相关的,不支持

    2. 关联数组用于indices/values of 表现与oracle不一致

    3. oracle的关联数组有exists方法,我们没有,改写失效

    --------------------------------------------------------------------
    --1 lower..higher
    DECLARE
      TYPE NumList IS TABLE OF NUMBER;
      depts  NumList := NumList(22,44,66);
    BEGIN
      FORALL j IN depts.FIRST..depts.LAST
        DELETE FROM emp_temp WHERE department_id = depts(j);
    END;
    /
    --1 改写
    DECLARE
      TYPE NumList IS TABLE OF NUMBER;
      depts  NumList := NumList(22,44,66);
    BEGIN
      FOR j IN depts.FIRST..depts.LAST
      loop
        DELETE FROM emp_temp WHERE department_id = depts(j);
      end loop;
    END;
    /
    --2a indices of collection between .. and ..
    DECLARE
      TYPE NumList IS TABLE OF NUMBER;
      depts  NumList := NumList(11, 22, 44, 66);
    BEGIN
      FORALL j IN indices of depts between depts.first + 1 and depts.last
        DELETE FROM emp_temp WHERE department_id = depts(j);
    END;
    /
    --2a 改写
    DECLARE
      TYPE NumList IS TABLE OF NUMBER;
      depts  NumList := NumList(11, 22, 44, 66);
    BEGIN
      FOR j IN depts.first+1..depts.last
      loop
       --dbms_output.put_line(j);
       if depts.exists(j) then
          DELETE FROM emp_temp WHERE department_id = depts(j);
       end if;
       end loop;
    END;
    /
    --2b indices of collection
    DECLARE
      TYPE NumList IS TABLE OF NUMBER;
      depts  NumList := NumList(22, 44, 66);
    BEGIN
      FORALL j IN indices of depts
        DELETE FROM emp_temp WHERE department_id = depts(j);
    END;
    /
    --2b 改写
    DECLARE
      TYPE NumList IS TABLE OF NUMBER;
      depts  NumList := NumList(22, 44, 66);
    BEGIN
      FOR j IN depts.first..depts.last
      loop
       --dbms_output.put_line(j);
       if depts.exists(j) then
          DELETE FROM emp_temp WHERE department_id = depts(j);
       end if;
       end loop;
    END;
    /
    --3  values of
    DECLARE
      TYPE NumList IS TABLE OF NUMBER;
      depts  NumList := NumList(22,44,66);
    
      TYPE NumListInt IS TABLE OF int;
      keys  NumListInt := NumListInt(1,2,3);
    BEGIN
      FORALL j IN values of keys
        DELETE FROM emp_temp WHERE department_id = depts(j);
    END;
    /
    --3 改写
    DECLARE
      TYPE NumList IS TABLE OF NUMBER;
      depts  NumList := NumList(22,44,66);
      TYPE NumListInt IS TABLE OF int;
      keys  NumListInt := NumListInt(1,2,3);
    BEGIN
      FOR j IN keys.first..keys.last
      loop
       --dbms_output.put_line(j);
       if keys.exists(j) then
          DELETE FROM emp_temp WHERE department_id = depts(keys(j));
       end if;
      end loop;
    END;
    /
    ------------------------------------------------------------------ end
    
    
    ------------如果要测试,先执行以下
    CREATE TABLE employees(
      employee_id    NUMBER(6),
      first_name     VARCHAR2(20),
      last_name      VARCHAR2(25),
      department_id  NUMBER(4),
      salary         NUMBER(6)
    );
    INSERT INTO employees VALUES (1,'zhang','san',11,10);
    INSERT INTO employees VALUES (2,'li','si',22,20);
    INSERT INTO employees VALUES (3,'liu','xiang',33,30);
    INSERT INTO employees VALUES (4,'sun','yang',44,40);
    INSERT INTO employees VALUES (5,'ye','shiwen',55,50);
    INSERT INTO employees VALUES (6,'chen','yibing',66,60);
    
    --
    INSERT INTO emp_temp VALUES (2,'li','si',22,20);
    INSERT INTO emp_temp VALUES (4,'sun','yang',44,40);
    INSERT INTO emp_temp VALUES (6,'chen','yibing',66,60);
    
    SELECT * FROM employees;
    
    CREATE TABLE emp_temp AS
    SELECT * FROM employees
    ORDER BY employee_id, department_id;
    
    SELECT * from emp_temp;
    drop table emp_temp;
    drop table employees;
    
    ----------------------------------------------------------------
    --存在的问题
    --关联数组的情况, 不一致
    --2
    DECLARE
      TYPE NumList IS TABLE OF pls_integer index by pls_integer;
      depts  NumList;
    BEGIN
      depts(1) := 1;
      depts(3) := 2;
      depts(5) := 3;
    
      FORALL j IN indices of depts between depts.first and depts.last
        DELETE FROM emp_temp WHERE department_id = depts(j);
    END;
    /
    --3  values of
    DECLARE
      TYPE NumList IS TABLE OF NUMBER;
      depts  NumList := NumList(22,44,66);
    
      TYPE NumListInt IS TABLE OF pls_integer index by pls_integer;
      keys  NumListInt;
    BEGIN
      keys(1) := 1;
      keys(3) := 2;
      keys(5) := 3;
    
      FORALL j IN values of keys
        DELETE FROM emp_temp WHERE department_id = depts(j);
    END;
    /
    
    
    ------------------
     CREATE OR REPLACE PACKAGE BODY "CDS"."CDS_PKG_COMMON_FUNC" IS v_g_Debug BOOLEAN := FALSE;
     PROCEDURE CDS_P_DEBUG_SET(in_debug IN BOOLEAN) IS BEGIN  v_g_Debug := in_debug; END CDS_P_DEBUG_SET;
    
     FUNCTION CDS_F_SPLIT_DATA (source_data IN VARCHAR2, delimiter_data IN VARCHAR2)  RETURN cds_t_str_split IS
       j         INT := 0;
       i         INT := 1;
       source_data_len  INT := 0;
       delimiter_data_len INT := 0;
       str        VARCHAR2(4000);
       str_split     cds_t_str_split := cds_t_str_split();
    BEGIN
      source_data_len  := LENGTH(source_data);
      delimiter_data_len := LENGTH(delimiter_data);
    
      WHILE j < source_data_len LOOP   j := INSTR(source_data, delimiter_data, i);
    
    
       IF j = 0 THEN
          j := source_data_len;
          str := SUBSTR(source_data, i);
          str_split.EXTEND;
          str_split(str_split.COUNT) := trim(str);
          IF i >= source_data_len THEN
             EXIT;
          END IF;
       ELSE
          str := SUBSTR(source_data, i, j - i);
          if str is not null then     str_split.EXTEND;
             str_split(str_split.COUNT) := trim(str);
          end if;
          i := j + delimiter_data_len;
          END IF;
    
       END LOOP;
      RETURN str_split; END;
    END CDS_PKG_COMMON_FUNC;
    
    ---
    
    
    declare
      TYPE t_student_var IS TABLE OF VARCHAR2(100);
      v_tbl_name t_student_var := t_student_var();--初始化
    BEGIN
      raise notice 'v_tbl_name: %', v_tbl_name;
      v_tbl_name.extend;--扩展空间
      select x into v_tbl_name(1) from test1 where id = 1;
      v_tbl_name.extend;--扩展空间
      select x into v_tbl_name(2) from test1 where id = 2;
      v_tbl_name.extend;--扩展空间
      select x into v_tbl_name(3) from test1 where id = 3;
      dbms_output.put_line('v_tbl_name(1): %'|| v_tbl_name(1));
      dbms_output.put_line('v_tbl_name(2): %', v_tbl_name(2);
      dbms_output.put_line('v_tbl_name(3): %', v_tbl_name(3);
      raise notice 'v_tbl_name: %', v_tbl_name;
    end;
    
    
    
    CREATE OR REPLACE PACKAGE CDS_PKG_COMMON_FUNC AS
      FUNCTION CDS_F_SPLIT_DATA(source_data IN VARCHAR2, delimiter_data IN VARCHAR2) RETURN cds_t_str_split;
    END CDS_PKG_COMMON_FUNC;
    
    CREATE OR REPLACE PACKAGE BODY CDS_PKG_COMMON_FUNC IS
      v_g_Debug BOOLEAN := FALSE;
      PROCEDURE CDS_P_DEBUG_SET(in_debug IN BOOLEAN) IS
      BEGIN
        v_g_Debug := in_debug;
      END CDS_P_DEBUG_SET;
    
      FUNCTION CDS_F_SPLIT_DATA(source_data IN VARCHAR2, delimiter_data IN VARCHAR2)
        RETURN cds_t_str_split IS
        j                  INT := 0;
        i                  INT := 1;
        source_data_len    INT := 0;
        delimiter_data_len INT := 0;
        str                VARCHAR2(4000);
        str_split          cds_t_str_split := cds_t_str_split();
      BEGIN
        source_data_len    := LENGTH(source_data);
        delimiter_data_len := LENGTH(delimiter_data);
        WHILE j < source_data_len LOOP
          j := INSTR(source_data, delimiter_data, i);
          IF j = 0 THEN
            j   := source_data_len;
            str := SUBSTR(source_data, i);
            str_split.EXTEND;
            str_split(str_split.COUNT) := trim(str);
            IF i >= source_data_len THEN
              EXIT;
            END IF;
          ELSE
            str := SUBSTR(source_data, i, j - i);
            if str is not null then
              str_split.EXTEND;
              str_split(str_split.COUNT) := trim(str);
            end if;
            i := j + delimiter_data_len;
          END IF;
        END LOOP;
        RETURN str_split;
      END;
    END CDS_PKG_COMMON_FUNC;
    

    2.1.4.3. oracle语法指定语言

    区别:

    V8.3创建oracle语法函数时能够指定LANGUAGE xxx语言

    V8.6 创建oracle语法函数时不支持指定LANGUAGE xxx语言

    升级改写方案:

    删除LANGUAGE xxx语言子句

    V8.3:

    CREATE OR REPLACE function pr1 return int
    LANGUAGE plsql
    AS
    BEGIN
          return 1;
    END;
    

    V8.6 :

    CREATE OR REPLACE function pr1 return int
    AS
    BEGIN
          return 1;
    END;
    

    2.1.4.4. 嵌套表定义CHAR类型省略长度

    区别:

    V8.3嵌套表定义CHAR类型省略长度,赋值超长, V8.3截断

    V8.6 嵌套表定义CHAR类型省略长度,赋值超长,|version|报错

    升级改写方案:

    嵌套表定义CHAR类型省略长度,赋值正确

    V8.3:

    DO $$DECLARE
       TYPE type_name10 IS TABLE OF CHAR NOT NULL;
       nttypeelement10 type_name10:=type_name10('AAAA');
    BEGIN
       RAISE NOTICE 'nttypeelement10(1)=%',nttypeelement10(1);
       EXCEPTION WHEN VALUE_ERROR THEN
       RAISE NOTICE 'VALUE_ERROR';
    END$$;
    

    V8.6 :

    DO $$DECLARE
       TYPE type_name10 IS TABLE OF CHAR NOT NULL;
       nttypeelement10 type_name10:=type_name10('A');
    BEGIN
       RAISE NOTICE 'nttypeelement10(1)=%',nttypeelement10(1);
       EXCEPTION WHEN VALUE_ERROR THEN
       RAISE NOTICE 'VALUE_ERROR';
    END$$;
    

    2.1.4.5. CREATE PACKAGE

    区别:

    V8.3CREATE PACKAGE 中文名的包 AS a int END;创建成功

    V8.6 CREATE PACKAGE 中文名的包 AS a int END;创建失败

    升级改写方案:

    由于R6在包语法解析时更加严格,因此需要在a int后加’;’

    V8.3:

    CREATE PACKAGE 中文名的包 AS a int END;
    

    V8.6 :

    CREATE PACKAGE 中文名的包 AS a int; END;
    

    2.1.5. 版本新增能力和变更能力明细

    V8.6 和 V8.3 版本新增以及变更能力明细如下表所示:

    表 2.1.5 V8.6 和 V8.3 版本新增以及变更能力明细

    功能增强

    实现完整性

    数据库对象类型

    支持全局临时表

    完整实现

    Oracle directory

    不完整,不包括授权

    支持Generated columns;

    完整实现

    支持分区

    不完整, 不支持分区的alter,不支 持全局索引,不支持 interval分区和reference 分区

    兼容oracle 默认是大写存储的行为

    不完 整,不支持oracle中大写 对象和小写对象同时存在

    支持兼容oracle的 Force View

    完整实现

    服务器编 码新增支持GBK、GB18030

    完整实现

    支持自动任务调度

    完整实现

    支持同义词

    完整实现

    内置数据库对象

    支持XML函数

    完整实现

    支持postgis 2.5.2 和 3.0

    支持linux

    支持oracle系统视图

    完整实现

    支持兼容Oracle 数据类型:Number、字符 类型、日期时间型、同时 支持相关的操作符、索引 、函数,支持类型转换。

    完整实现

    支持BLOB、CLOB、NCLOB等 大对象数据类型,同时支 持了相关的函数、接口。

    完整实现

    SQL操作

    支持表达式coalesce

    完整实现

    支持不指定group by情况下进行聚集操作

    完整实现

    支持Merge into

    完整实现

    支持dml语句使 用return指定返回结果集

    完整实现

    支持子查询自动生成别名

    完整实现

    支持中文的逗号和空格

    完整实现

    新增约束的禁用启用

    完整实现

    支持在create table时指定列为not null

    完整实现

    支持在create user时指定lock和unlock

    完整实现

    支持在线重建index

    完整实现

    支持内嵌WITH recursive 查询;

    完整实现

    支持 SQL/JSON PATH特性;

    完整实现

    2.1.6. 支持的客户端编程接口兼容性

    V8.6 和 V8.3 客户端编程接口兼容性如下表所示:

    表 2.1.6 V8.6 和 V8.3 客户端编程接口兼容性

    接口类型

    V8.3和V8.6的兼容性

    JDBC

    读写分离集群增加一个必填参数:nodelist,其它方面使用一致。

    Activiti

    直接使用PG的配置方式,使用JDBC的PG形态驱动包。

    Hibernate

    一致

    OCI

    一致

    Mybatis

    一致

    ODBC

    一致

    NET NDP

    一致

    NET EF

    一致

    PHP PDO

    一致

    Perl PDI

    一致

    Nodejs

    一致

    Golang

    一致

    Python

    一致

    QT

    一致

  • 相关阅读:
    Combiner和Partitioner
    利用TypeScript 和 jsdom 库实现自动化抓取数据
    【LeetCode热题100】--20.有效的括号
    数据结构与算法基础-(4)
    steam游戏找不到steam_api64.dll,分享三个有效的解决方法
    银行纷纷入局数字藏品,元宇宙电商-NFG系统有何作为呢?
    第十章:异常
    核医学重点归纳
    【Linux】虚拟机部署与发布J2EE项目(Windows版本)
    tomcat探究二搭建简单的servlet容器
  • 原文地址:https://blog.csdn.net/arthemis_14/article/details/126028701