瀚高数据库V9.0 Oracle兼容性深度解析:从迁移到适配
前言
在国产化替代浪潮中,从 Oracle 迁移到国产数据库的最大障碍就是兼容性。瀚高数据库 V9.0 提供了业界领先的 Oracle 兼容能力,覆盖了数据类型、内置函数、PL/SQL、存储过程、包、同义词、DBLink、闪回等数十项核心特性。
本文基于官方 Oracle 兼容性手册,系统梳理 HGDB V9.0 的 Oracle 兼容体系,帮助运维和开发人员平稳完成数据库迁移。
一、兼容性全景图
HGDB V9.0 的 Oracle 兼容性覆盖以下层次:
┌─────────────────────────────────────────────────────┐
│ 应用层 │
│ 存储过程 / 函数 / 包 / 同义词 / DBLink / 触发器 │
├─────────────────────────────────────────────────────┤
│ SQL 层 │
│ MERGE / CONNECT BY / ROWNUM / (+)连接 / 序列 │
├─────────────────────────────────────────────────────┤
│ 函数层 │
│ 100+ Oracle 内置函数 / 分析函数 / 转换函数 │
├─────────────────────────────────────────────────────┤
│ 类型层 │
│ NUMBER / VARCHAR2 / DATE / TIMESTAMP / CLOB / BLOB │
├─────────────────────────────────────────────────────┤
│ 系统层 │
│ 系统视图 / 数据字典 / 系统包 (DBMS_*) │
└─────────────────────────────────────────────────────┘
二、数据类型兼容
2.1 完整的数据类型映射
HGDB V9.0 直接支持以下 Oracle 原生数据类型,无需修改表结构:
-- Oracle 原生类型在 HGDB 中直接可用
CREATE TABLE employee (
emp_id NUMBER(10), -- 数值类型
emp_name VARCHAR2(100), -- 变长字符串
hire_date DATE, -- 日期(含时间)
salary NUMBER(10,2),
bonus BINARY_FLOAT, -- 单精度浮点
commission BINARY_DOUBLE, -- 双精度浮点
created_at TIMESTAMP, -- 时间戳
tz_time TIMESTAMP WITH TIME ZONE,
local_tz TIMESTAMP WITH LOCAL TIME ZONE,
work_period INTERVAL YEAR TO MONTH, -- 年月间隔
task_time INTERVAL DAY TO SECOND, -- 日时间隔
resume CLOB, -- 大文本
photo BLOB -- 二进制
);
关键类型说明:
| Oracle 类型 | HGDB 支持 | 说明 |
|---|---|---|
| NUMBER(p,s) | 原生支持 | 与 Oracle 精度一致 |
| VARCHAR2(n) | 原生支持 | 字符串比较规则与 Oracle 一致 |
| DATE | 原生支持 | 含时分秒 |
| TIMESTAMP | 原生支持 | 纳秒精度 |
| TIMESTAMP WITH TIME ZONE | 原生支持 | 含时区信息 |
| INTERVAL YEAR TO MONTH | 原生支持 | 年月间隔计算 |
| INTERVAL DAY TO SECOND | 原生支持 | 日时间隔计算 |
| BINARY_FLOAT/DOUBLE | 原生支持 | IEEE 754 浮点 |
| CLOB/BLOB | 原生支持 | 大对象存储 |
2.2 日期函数完整兼容
-- 以下 Oracle 日期函数在 HGDB 中全部可用
SELECT
SYSDATE, -- 当前日期时间
SYSTIMESTAMP, -- 当前时间戳
ADD_MONTHS(hire_date, 6) AS after_6_months,
LAST_DAY(hire_date) AS month_end,
NEXT_DAY(hire_date, 'MONDAY') AS next_monday,
MONTHS_BETWEEN(SYSDATE, hire_date) AS work_months,
ROUND(hire_date, 'MONTH') AS rounded,
TRUNC(hire_date, 'YEAR') AS year_start,
TO_DATE('2026-07-01', 'YYYY-MM-DD'),
TO_CHAR(hire_date, 'YYYY年MM月DD日') AS cn_date,
TO_TIMESTAMP('2026-07-01 14:30:00', 'YYYY-MM-DD HH24:MI:SS'),
EXTRACT(YEAR FROM hire_date) AS hire_year
FROM employee;
2.3 字符串与转换函数
-- 字符串处理
SELECT
LENGTH('瀚高数据库'), -- 字符长度
LENGTHB('瀚高数据库'), -- 字节长度
SUBSTR(emp_name, 1, 3),
INSTR(emp_name, '张'),
LPAD(emp_id, 8, '0'),
REPLACE(emp_name, ' ', ''),
CONCAT(first_name, last_name)
FROM employee;
-- 类型转换
SELECT
TO_NUMBER('12345.67'),
TO_CHAR(salary, 'L999,999.00'),
NVL(bonus, 0), -- NULL 替换
NVL2(bonus, '有奖金', '无奖金'),
DECODE(status, 1, '在职', 2, '离职', '未知'),
COALESCE(bonus, commission, 0)
FROM employee;
三、PL/SQL 兼容 — 存储过程与函数
HGDB V9.0 全面兼容 Oracle PL/SQL 语法:
-- Oracle 风格的存储过程
CREATE OR REPLACE PROCEDURE update_salary(
p_emp_id IN NUMBER,
p_increase IN NUMBER DEFAULT 0.1,
p_new_sal OUT NUMBER
) AS
v_old_salary NUMBER;
BEGIN
SELECT salary INTO v_old_salary
FROM employee WHERE emp_id = p_emp_id;
p_new_sal := v_old_salary * (1 + p_increase);
UPDATE employee
SET salary = p_new_sal
WHERE emp_id = p_emp_id;
COMMIT;
EXCEPTION
WHEN NO_DATA_FOUND THEN
RAISE_APPLICATION_ERROR(-20001, '员工不存在');
WHEN OTHERS THEN
ROLLBACK;
RAISE;
END;
/
-- 调用存储过程
DECLARE
v_sal NUMBER;
BEGIN
update_salary(1001, 0.15, v_sal);
DBMS_OUTPUT.PUT_LINE('新工资: ' || v_sal);
END;
/
支持的特殊语法:
-- 嵌套函数(Oracle 特有)
CREATE OR REPLACE FUNCTION calc_bonus(p_salary NUMBER) RETURN NUMBER AS
FUNCTION calc_tax(p_amount NUMBER) RETURN NUMBER AS
BEGIN
RETURN p_amount * 0.03;
END;
BEGIN
RETURN p_salary - calc_tax(p_salary);
END;
/
-- 自治事务
CREATE OR REPLACE PROCEDURE log_access(p_user VARCHAR2) AS
PRAGMA AUTONOMOUS_TRANSACTION;
BEGIN
INSERT INTO access_log(user_name, access_time)
VALUES (p_user, SYSDATE);
COMMIT;
END;
/
四、包(PACKAGE)与系统包
4.1 自定义包
-- 创建包规范
CREATE OR REPLACE PACKAGE emp_pkg AS
FUNCTION get_salary(p_emp_id NUMBER) RETURN NUMBER;
PROCEDURE raise_salary(p_emp_id NUMBER, p_pct NUMBER);
END emp_pkg;
/
-- 创建包体
CREATE OR REPLACE PACKAGE BODY emp_pkg AS
FUNCTION get_salary(p_emp_id NUMBER) RETURN NUMBER AS
v_sal NUMBER;
BEGIN
SELECT salary INTO v_sal FROM employee WHERE emp_id = p_emp_id;
RETURN v_sal;
END;
PROCEDURE raise_salary(p_emp_id NUMBER, p_pct NUMBER) AS
BEGIN
UPDATE employee SET salary = salary * (1 + p_pct)
WHERE emp_id = p_emp_id;
COMMIT;
END;
END emp_pkg;
/
-- 调用包
SELECT emp_pkg.get_salary(1001) FROM dual;
EXEC emp_pkg.raise_salary(1001, 0.1);
4.2 系统包支持
HGDB V9.0 内置了以下 Oracle 兼容系统包:
| 系统包 | 功能 |
|---|---|
| DBMS_OUTPUT | 调试输出 |
| DBMS_JOB | 定时任务调度 |
| DBMS_SQL | 动态 SQL 执行 |
| DBMS_LOB | 大对象操作 |
| UTL_FILE | 文件读写 |
| DBMS_RANDOM | 随机数生成 |
-- DBMS_JOB 创建定时任务
DECLARE
job_id NUMBER;
BEGIN
DBMS_JOB.SUBMIT(
job => job_id,
what => 'update_salary_daily;',
next_date => TRUNC(SYSDATE) + 1,
interval => 'TRUNC(SYSDATE) + 1'
);
COMMIT;
END;
/
-- DBMS_OUTPUT 调试
BEGIN
DBMS_OUTPUT.PUT_LINE('处理开始...');
FOR rec IN (SELECT emp_id, emp_name FROM employee) LOOP
DBMS_OUTPUT.PUT_LINE('处理员工: ' || rec.emp_name);
END LOOP;
END;
/
五、同义词(SYNONYM)
HGDB V9.0 完整支持 Oracle 同义词机制:
-- 创建私有同义词
CREATE SYNONYM emp FOR hr.employee;
-- 创建公共同义词
CREATE PUBLIC SYNONYM pub_emp FOR hr.employee;
-- 使用同义词
SELECT * FROM emp; -- 等同于 SELECT * FROM hr.employee;
INSERT INTO emp VALUES(...);
-- 删除同义词
DROP SYNONYM emp;
DROP PUBLIC SYNONYM pub_emp;
同义词在 DML 和 DDL 语句中均可使用,支持跨 Schema 引用。
六、MERGE 语句与序列
-- MERGE 语句(Oracle 风格)
MERGE INTO employee e
USING (SELECT emp_id, new_salary FROM salary_update) s
ON (e.emp_id = s.emp_id)
WHEN MATCHED THEN
UPDATE SET e.salary = s.new_salary
WHEN NOT MATCHED THEN
INSERT (emp_id, salary) VALUES (s.emp_id, s.new_salary);
-- 序列(Sequence)
CREATE SEQUENCE emp_seq
START WITH 1000
INCREMENT BY 1
MAXVALUE 999999
CACHE 20;
-- 自增列(IDENTITY)
CREATE TABLE orders (
order_id NUMBER GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY,
order_no VARCHAR2(50),
created DATE DEFAULT SYSDATE
);
七、DBLink — 跨数据库访问
-- 创建 DBLink 到远程 Oracle 数据库
CREATE EXTENSION oracle_fdw;
CREATE SERVER oracle_server
FOREIGN DATA WRAPPER oracle_fdw
OPTIONS (dbserver '//192.168.1.100:1521/ORCL');
CREATE USER MAPPING FOR highgo
SERVER oracle_server
OPTIONS (user 'scott', password 'tiger');
-- 创建外部表映射
CREATE FOREIGN TABLE remote_emp (
emp_id INTEGER,
ename VARCHAR(50),
sal NUMERIC(10,2)
) SERVER oracle_server
OPTIONS (schema 'SCOTT', table 'EMP');
-- 直接查询远程表
SELECT * FROM remote_emp WHERE sal > 3000;
八、分区表兼容
8.1 Interval 分区(Oracle 11g+ 特性)
-- 按月自动创建分区
CREATE TABLE sales (
sale_id NUMBER,
sale_date DATE,
amount NUMBER(12,2)
) PARTITION BY RANGE (sale_date) INTERVAL (NUMTOYMINTERVAL(1, 'MONTH'))
(
PARTITION p202601 VALUES LESS THAN (TO_DATE('2026-02-01', 'YYYY-MM-DD'))
);
-- 插入数据会自动创建缺失的分区
INSERT INTO sales VALUES (1, DATE '2026-07-15', 50000);
-- 自动创建 p202607 分区!
8.2 分区表维护
-- 手动创建 Interval 分区
ALTER TABLE sales ADD PARTITION
p_manual VALUES LESS THAN (TO_DATE('2026-08-01', 'YYYY-MM-DD'));
-- 修改分区间隔
ALTER TABLE sales SET INTERVAL (NUMTOYMINTERVAL(1, 'QUARTER'));
-- 删除分区
ALTER TABLE sales DROP PARTITION p202601;
-- 分离分区(转为普通表)
ALTER TABLE sales DETACH PARTITION p202601;
九、其他重要兼容特性
9.1 闪回(Flashback)
-- 闪回查询(查看历史数据)
SELECT * FROM employee AS OF TIMESTAMP
TO_TIMESTAMP('2026-07-01 10:00:00', 'YYYY-MM-DD HH24:MI:SS');
-- 闪回表到删除前(回收站功能)
FLASHBACK TABLE employee TO BEFORE DROP;
-- 清空回收站
PURGE RECYCLEBIN;
9.2 ROWNUM 和 CONNECT BY
-- ROWNUM 支持
SELECT * FROM employee WHERE ROWNUM <= 10;
-- 层次查询
SELECT emp_id, emp_name, manager_id, LEVEL
FROM employee
START WITH manager_id IS NULL
CONNECT BY PRIOR emp_id = manager_id;
9.3 SUBTYPE 类型
-- 定义子类型(带约束)
DECLARE
SUBTYPE pos_number IS NUMBER(10,2) NOT NULL;
v_salary pos_number := 5000.00;
BEGIN
DBMS_OUTPUT.PUT_LINE(v_salary);
END;
/
十、迁移工具与流程
HGDB V9.0 提供专用的迁移工具,支持从 Oracle 自动迁移:
# 迁移工具核心功能:
# 1. 自动扫描 Oracle Schema 对象
# 2. 类型映射(Oracle → HGDB)
# 3. 数据迁移(全量 + 增量)
# 4. 存储过程/函数/包自动转换
# 5. 迁移校验报告
迁移流程建议:
1. 评估阶段
├── 扫描 Oracle 对象清单
├── 识别不兼容的功能
└── 制定迁移方案
2. 迁移阶段
├── 结构迁移(DDL)
├── 数据迁移(全量)
├── 对象迁移(存储过程等)
└── 增量同步
3. 验证阶段
├── 数据一致性校验
├── 功能测试
└── 性能基准测试
4. 切换阶段
├── 最终增量同步
├── 业务割接
└── 监控观察
总结
瀚高数据库 V9.0 的 Oracle 兼容能力覆盖了生产环境中最常用的 90%+ 特性,从数据类型到 PL/SQL、从包到同义词、从 DBLink 到闪回,形成了一个完整的 Oracle 兼容生态。
迁移前的关键评估点:
| 评估项 | 兼容度 | 注意事项 |
|---|---|---|
| 数据类型 | 高 | NUMBER/VARCHAR2/DATE 直接支持 |
| 内置函数 | 高 | 100+ 函数覆盖 |
| PL/SQL | 中高 | 存储过程、包、自治事务支持 |
| 系统包 | 中 | DBMS_OUTPUT/DBMS_JOB 等核心包可用 |
| 分区表 | 高 | Interval 分区完整支持 |
| 闪回 | 高 | 查询和表级闪回支持 |
| DBLink | 中 | 通过 FDW 实现 |
迁移原则:先评估、后迁移、逐模块验证,切忌一次性全量切换。对于不兼容的特性,提前制定好替代方案。