数据库运维13 min read

Vastbase G100 Oracle 兼容性深度解析

Vastbase G100 Oracle 兼容性深度解析

国产数据库替代 Oracle,最大的难点不是性能,而是兼容性。应用系统经过多年迭代,积累了大量 Oracle 特有语法、存储过程、触发器,改写成本极高。Vastbase G100 的核心卖点就是 Oracle 兼容——官方兼容性手册有 1799 页,覆盖了从数据类型到 PL/SQL 的方方面面。本文从中提炼关键内容,帮助评估迁移可行性。

兼容性架构

Vastbase G100 的 Oracle 兼容不是简单的语法翻译,而是从内核层面实现的深度兼容。初始化数据库时指定 DBCOMPATIBILITY='A' 即启用 Oracle 兼容模式,此后数据库的行为在多个层面模拟 Oracle:

  • 数据类型层:支持 Oracle 全部内置数据类型,包括 NUMBER、VARCHAR2、DATE、BLOB/CLOB、BFILE 等
  • 函数层:兼容 200+ Oracle 内置函数
  • PL/SQL 层:支持存储过程、函数、包、触发器,语法高度兼容
  • SQL 语法层:支持 DUAL 表、ROWNUM、CONNECT BY 层次查询、MERGE INTO 等
  • 对象管理层:支持序列、同义词、物化视图、目录对象等

数据类型兼容

数值类型

Oracle 类型 Vastbase 支持 说明
NUMBER 精度和标量完全兼容
NUMBER(p,s) 支持指定精度和标量
BINARY_FLOAT 4 字节单精度浮点
BINARY_DOUBLE 8 字节双精度浮点
PLS_INTEGER 整数类型
FLOAT 浮点类型
-- NUMBER 类型测试
CREATE TABLE num_test (
    id NUMBER,
    price NUMBER(10,2),
    ratio NUMBER(5,4)
);

INSERT INTO num_test VALUES (1, 99999999.99, 0.9999);
SELECT * FROM num_test;

字符类型

Oracle 类型 Vastbase 支持 最大长度 说明
VARCHAR2 32767 字节 可变长字符
CHAR 2000 字节 定长字符
NCHAR 2000 字符 国家字符集定长
NVARCHAR2 32767 字符 国家字符集可变长
LONG 2GB 可变长字符串(不推荐)
CLOB 1GB-1 字符大对象
NCLOB 1GB-1 国家字符集大对象

LONG 类型注意:一个表只能有一个 LONG 列,不能出现在 WHERE、GROUP BY、ORDER BY 中,不能创建索引。Vastbase 完全继承了这些限制,建议迁移时改用 CLOB。

日期时间类型

Oracle 类型 Vastbase 支持 说明
DATE 存储日期和时间(精度到秒)
TIMESTAMP 带小数秒的时间戳
TIMESTAMP WITH TIME ZONE 带时区
INTERVAL YEAR TO MONTH 年月间隔
INTERVAL DAY TO SECOND 天秒间隔

DATE 类型是迁移中最常用的类型。Vastbase 的 DATE 类型行为与 Oracle 完全一致:

-- DATE 类型行为测试
SELECT sysdate FROM dual;
-- 返回: 2026-07-03 10:30:00

-- 日期相减返回天数(NUMBER 类型)
SELECT to_date('2026-07-10','yyyy-mm-dd') - to_date('2026-07-01','yyyy-mm-dd') FROM dual;
-- 返回: 9

-- 日期相减再做乘法返回数值
SELECT (sysdate - to_date('2026-01-01','yyyy-mm-dd')) * 86400 FROM dual;
-- 返回从年初到现在的秒数

大对象类型

BLOB 和 CLOB 是 Oracle 应用中最常见的大对象类型,Vastbase 通过 TOAST 表存储未经压缩的原始数据:

-- CLOB 基本操作
CREATE TABLE doc_test (
    id NUMBER PRIMARY KEY,
    content CLOB,
    created DATE DEFAULT sysdate
);

INSERT INTO doc_test VALUES (1, TO_CLOB('测试文本'), sysdate);
SELECT id, content, TO_CHAR(created, 'yyyy-mm-dd') FROM doc_test;

-- BLOB 通过 DBMS_LOB 管理
DECLARE
    v_blob BLOB;
BEGIN
    SELECT content INTO v_blob FROM blob_test WHERE id = 1;
    DBMS_LOB.OPEN(v_blob, DBMS_LOB.LOB_READWRITE);
    DBMS_LOB.WRITEAPPEND(v_blob, 10, UTL_RAW.CAST_TO_RAW('append_data'));
    DBMS_LOB.CLOSE(v_blob);
END;
/

大对象限制:不支持基于 BLOB/CLOB 创建索引;不支持直接比较操作;列存表不支持 BLOB/CLOB 类型;不支持修改表中 LOB 列类型。

BFILE 类型

BFILE 是 Oracle 特有的只读外部文件引用类型,Vastbase 完整支持:

-- 1. 创建 directory 对象
CREATE DIRECTORY d_bfile AS '/home/vastbase';

-- 2. 创建包含 BFILE 列的表
CREATE TABLE test_bfile (
    id NUMBER,
    file_ref BFILE
);

-- 3. 插入数据
INSERT INTO test_bfile VALUES (1, BFILENAME('d_bfile', 'data.txt'));

-- 4. 查询
SELECT * FROM test_bfile;

函数兼容

Vastbase 兼容 200+ Oracle 内置函数,以下是最常用的分类总结:

数值函数

函数 说明 示例
MOD(n2, n1) 取模,n1=0 时返回 n2 MOD(10, 3) → 1
ROUND(n, d) 四舍五入 ROUND(3.14159, 2) → 3.14
TRUNC(n, d) 截断 TRUNC(3.14159, 2) → 3.14
CEIL(n) 向上取整 CEIL(3.1) → 4
FLOOR(n) 向下取整 FLOOR(3.9) → 3
POWER(n2, n1) 幂运算 POWER(2, 10) → 1024
BITAND(n1, n2) 按位与 BITAND(6, 3) → 2

字符函数

函数 说明
INSTR(str, sub, pos, nth) 查找子串位置
LENGTHB(char) 字节长度
LPAD(str, len, pad) 左填充
LTRIM(c1, c2) 左截断
REPLACE(str, search, replace) 替换
SUBSTR(str, pos, len) 截取子串
TRANSLATE(str, from, to) 字符映射
REGEXP_REPLACE 正则替换
REGEXP_SUBSTR 正则提取

日期函数

函数 说明
SYSDATE 当前日期时间
ADD_MONTHS(date, n) 月份加减
LAST_DAY(date) 月末日期
MONTHS_BETWEEN(d1, d2) 月份差
NEXT_DAY(date, char) 下一个指定星期
EXTRACT(field FROM date) 提取日期分量
TRUNC(date, fmt) 日期截断

分析函数

Vastbase 兼容 Oracle 分析函数(窗口函数)语法:

-- ROW_NUMBER 排名
SELECT ename, deptno, sal,
    ROW_NUMBER() OVER (PARTITION BY deptno ORDER BY sal DESC) rn
FROM emp;

-- LAG/LEAD 取偏移行
SELECT ename, sal,
    LAG(sal, 1, 0) OVER (ORDER BY sal) prev_sal,
    LEAD(sal, 1, 0) OVER (ORDER BY sal) next_sal
FROM emp;

-- RATIO_TO_REPORT 占比
SELECT ename, sal,
    RATIO_TO_REPORT(sal) OVER () sal_ratio
FROM emp;

特殊函数

函数 说明
DECODE(expr, s1, r1, ..., default) 条件匹配返回
NVL(expr, default) NULL 替换
NVL2(expr, val1, val2) 非 NULL 返回 val1
COALESCE(expr1, expr2, ...) 返回第一个非 NULL
LNNVL(condition) 条件取反(含 NULL 处理)
NANVL(n2, n1) NAN 替换
EMPTY_BLOB() / EMPTY_CLOB() 返回空 LOB
DUMP(text) 返回内部表示

PL/SQL 兼容

存储过程

CREATE OR REPLACE PROCEDURE transfer_account(
    p_from_id NUMBER,
    p_to_id NUMBER,
    p_amount NUMBER
) AS
    v_balance NUMBER;
BEGIN
    SELECT balance INTO v_balance FROM accounts WHERE id = p_from_id;
    
    IF v_balance < p_amount THEN
        RAISE_APPLICATION_ERROR(-20001, '余额不足');
    END IF;
    
    UPDATE accounts SET balance = balance - p_amount WHERE id = p_from_id;
    UPDATE accounts SET balance = balance + p_amount WHERE id = p_to_id;
    
    COMMIT;
EXCEPTION
    WHEN NO_DATA_FOUND THEN
        ROLLBACK;
        RAISE_APPLICATION_ERROR(-20002, '账户不存在');
    WHEN OTHERS THEN
        ROLLBACK;
        RAISE;
END;
/

自定义函数

CREATE OR REPLACE FUNCTION calc_tax(
    p_salary NUMBER,
    p_rate NUMBER DEFAULT 0.1
) RETURN NUMBER AS
    v_tax NUMBER;
BEGIN
    v_tax := p_salary * p_rate;
    RETURN v_tax;
END;
/

包(Package)

Vastbase 支持 Oracle 的包(Package)概念,将相关过程和函数组织在一起:

-- 创建包头
CREATE OR REPLACE PACKAGE account_pkg AS
    PROCEDURE deposit(p_id NUMBER, p_amount NUMBER);
    PROCEDURE withdraw(p_id NUMBER, p_amount NUMBER);
    FUNCTION get_balance(p_id NUMBER) RETURN NUMBER;
END account_pkg;
/

-- 创建包体
CREATE OR REPLACE PACKAGE BODY account_pkg AS
    PROCEDURE deposit(p_id NUMBER, p_amount NUMBER) IS
    BEGIN
        UPDATE accounts SET balance = balance + p_amount WHERE id = p_id;
        COMMIT;
    END;
    
    PROCEDURE withdraw(p_id NUMBER, p_amount NUMBER) IS
    BEGIN
        UPDATE accounts SET balance = balance - p_amount WHERE id = p_id;
        COMMIT;
    END;
    
    FUNCTION get_balance(p_id NUMBER) RETURN NUMBER IS
        v_bal NUMBER;
    BEGIN
        SELECT balance INTO v_bal FROM accounts WHERE id = p_id;
        RETURN v_bal;
    END;
END account_pkg;
/

触发器

CREATE OR REPLACE TRIGGER audit_trigger
AFTER INSERT OR UPDATE OR DELETE ON emp
FOR EACH ROW
DECLARE
    v_action VARCHAR2(20);
BEGIN
    IF INSERTING THEN
        v_action := 'INSERT';
    ELSIF UPDATING THEN
        v_action := 'UPDATE';
    ELSIF DELETING THEN
        v_action := 'DELETE';
    END IF;
    
    INSERT INTO audit_log (table_name, action, action_time)
    VALUES ('emp', v_action, sysdate);
END;
/

SQL 语法兼容

DUAL 表

SELECT sysdate FROM dual;
SELECT 1+1 FROM dual;
SELECT USER FROM dual;

ROWNUM

-- 分页查询
SELECT * FROM (
    SELECT t.*, ROWNUM rn FROM (
        SELECT * FROM emp ORDER BY sal DESC
    ) t WHERE ROWNUM <= 20
) WHERE rn > 10;

CONNECT BY 层次查询

SELECT employee_id, manager_id, LPAD(' ', LEVEL*2) || ename AS org_chart
FROM employees
START WITH manager_id IS NULL
CONNECT BY PRIOR employee_id = manager_id;

MERGE INTO

MERGE INTO target_table t
USING source_table s
ON (t.id = s.id)
WHEN MATCHED THEN
    UPDATE SET t.name = s.name, t.value = s.value
WHEN NOT MATCHED THEN
    INSERT (id, name, value) VALUES (s.id, s.name, s.value);

UPSERT

INSERT INTO emp (id, name, sal) VALUES (1, '张三', 5000)
ON CONFLICT (id) DO UPDATE SET sal = EXCLUDED.sal;

迁移评估清单

从 Oracle 迁移到 Vastbase G100 前,建议按以下清单逐项评估:

评估项 检查内容 风险等级
数据类型 检查是否使用了 Vastbase 不支持的类型
存储过程 PL/SQL 语法差异、动态 SQL 兼容性
触发器 复合触发器、INSTEAD OF 触发器
包变量、初始化块
自定义类型 RECORD 类型、对象类型、集合类型
DBMS_LOB LOB 操作接口完整性
DBMS_OUTPUT 输出缓冲区行为
UTL_FILE 文件操作接口
DBMS_SCHEDULER 作业调度
自定义聚合函数 ODCIAggregate 接口
Java 存储过程 数据库内嵌 Java 不支持
外部表 ORACLE_LOADER、ORACLE_DATAPUMP
物化视图 刷新策略、查询重写

高风险项:DBMS_SCHEDULER 调度、外部表、Java 存储过程是迁移中最容易出问题的部分。建议提前评估替代方案。

迁移工具

Vastbase 提供配套迁移工具 VDS(Vastbase Data Studio),功能包括:

  • 结构迁移:自动转换 Oracle DDL 为 Vastbase 语法
  • 数据迁移:全量/增量数据迁移
  • 应用适配:自动识别不兼容 SQL 并给出修改建议
  • 校验工具:迁移前后数据一致性校验

建议迁移流程:

  1. 使用 VDS 扫描 Oracle 数据库,生成兼容性报告
  2. 评估高风险项,制定适配方案
  3. 使用 VDS 自动迁移结构
  4. 手动适配不兼容的存储过程和触发器
  5. 执行数据迁移
  6. 应用适配测试
  7. 性能调优

总结

Vastbase G100 的 Oracle 兼容性在国产数据库中属于第一梯队。1799 页兼容性手册覆盖了绝大多数 Oracle 特性,常见的数据类型、函数、PL/SQL 语法基本可以无缝迁移。

需要重点关注的风险点:

  1. DBMS_SCHEDULER:调度功能可能需要改用操作系统 crontab 或应用层调度
  2. Java 存储过程:完全不支持,需要外移到应用层
  3. 外部表:接口和格式有差异,需要适配
  4. 自定义聚合函数:接口不完全兼容,可能需要重写

整体评估,对于标准 OLTP 业务系统,Vastbase G100 的 Oracle 兼容性可以覆盖 90%+ 的场景。剩余 10% 需要手动适配的部分,迁移工具能提供详细的修改建议,工作量可控。

分享:

相关文章

评论区