摘要:上半年突然收到通知,我们做的政府项目要求迁移数据库到KingbaseES,一开始没听说过这个数据库有点慌,经过一番学习觉得是国产很优秀数据库,金仓KES数据库深度兼容Oracle PL/SQL语法,支持存储过程、函数、包等高级特性,可平滑迁移核心业务逻辑。同时提供原生JSON支持和丰富函数,满足现代数据处理需求。通过KDTS/KDMS工具评估兼容性,进行充分测试和性能调优,金仓KES是企业数据库国产化替代的可靠选择。
引言:为什么PL/SQL兼容性是国产化迁移的"定心丸"?
在金融、政务、能源等关键行业的数据库国产化替代浪潮中,Oracle数据库的迁移是重中之重,也是难度最大的环节之一。其中,承载了核心业务逻辑的存储过程、函数、触发器等PL/SQL代码,因其复杂性和对数据库引擎的强依赖性,常常成为迁移路上最大的"拦路虎"。作为中国电子科技集团(CETC)旗下的核心数据库企业,电科金仓 的拳头产品------金仓KES数据库,将高兼容度的PL/SQL支持作为其核心能力,旨在从根本上降低迁移成本,保障业务平滑过渡。

本文将从实战角度,深度剖析金仓KES对Oracle风格PL/SQL的兼容能力,并展示其强大的现代数据处理能力(如JSON支持),为正在进行或规划国产化迁移的企业提供一份详实的技术参考。
一、金仓KES的PL/SQL引擎:深度兼容Oracle语法
金仓KES的PL/SQL引擎在设计上高度兼容Oracle,这意味着大部分Oracle的PL/SQL代码可以在KES中几乎不加修改地运行。这不仅包括基础语法,更涵盖了包(Package)、游标(Cursor)、异常处理(Exception Handling)等高级特性。
1.1 基础程序结构兼容
以下是一个典型的Oracle PL/SQL代码块,在KES中可以直接执行。
sql
-- 示例1:声明块、循环、条件判断的基础兼容性
DECLARE
-- 变量声明,类型与Oracle一致
v_emp_id NUMBER(10) := 1001;
v_emp_name VARCHAR2(50);
v_salary NUMBER(10, 2);
v_bonus NUMBER(10, 2) := 0;
CURSOR cur_emp IS SELECT employee_name, salary FROM employees WHERE employee_id = v_emp_id;
BEGIN
-- 打开游标并获取数据
OPEN cur_emp;
FETCH cur_emp INTO v_emp_name, v_salary;
CLOSE cur_emp;
-- 条件判断逻辑(支持ELSIF)
IF v_salary > 10000 THEN
v_bonus := v_salary * 0.2;
ELSIF v_salary BETWEEN 5000 AND 10000 THEN
v_bonus := v_salary * 0.15;
ELSE
v_bonus := v_salary * 0.1;
END IF;
-- 使用DBMS_OUTPUT进行输出(KES内置兼容包)
DBMS_OUTPUT.PUT_LINE('员工: ' || v_emp_name || ',薪资: ' || v_salary || ',奖金: ' || v_bonus);
EXCEPTION
-- 异常处理块
WHEN NO_DATA_FOUND THEN
DBMS_OUTPUT.PUT_LINE('未找到对应的员工记录。');
WHEN OTHERS THEN
DBMS_OUTPUT.PUT_LINE('发生错误: ' || SQLERRM);
END;
/
代码解读与KES兼容点:
1、DECLARE块、BEGIN...END块的结构完全一致。
2、数据类型(NUMBER, VARCHAR2)、游标定义和使用方式相同。
3、条件控制流(IF-THEN-ELSIF-ELSE)语法一致。
4、内置包DBMS_OUTPUT的用法完全相同,KES提供了高兼容度的实现。
5、异常处理机制(EXCEPTION块)和内置异常(如NO_DATA_FOUND)得到支持。
1.2 存储过程与函数的创建与调用
存储过程和函数是PL/SQL的核心。KES在创建语法、参数模式(IN, OUT, IN OUT)等方面提供了出色兼容。
sql
-- 示例2:创建带有OUT参数的存储过程
CREATE OR REPLACE PROCEDURE sp_calculate_bonus(
p_emp_id IN NUMBER,
p_bonus_percentage IN NUMBER DEFAULT 0.1,
p_bonus_amount OUT NUMBER,
p_status OUT VARCHAR2
)
IS
v_salary NUMBER;
BEGIN
-- 查询员工薪资(增:SELECT INTO)
SELECT salary INTO v_salary
FROM employees
WHERE employee_id = p_emp_id;
-- 计算奖金(改:业务逻辑计算)
p_bonus_amount := v_salary * p_bonus_percentage;
p_status := 'SUCCESS';
EXCEPTION
WHEN NO_DATA_FOUND THEN
p_bonus_amount := 0;
p_status := 'ERROR: Employee not found.';
WHEN OTHERS THEN
p_bonus_amount := 0;
p_status := 'ERROR: ' || SQLERRM;
END sp_calculate_bonus;
/
-- 调用该存储过程(查:调用并获取结果)
DECLARE
v_amount NUMBER;
v_status VARCHAR2(100);
BEGIN
sp_calculate_bonus(p_emp_id => 1001, p_bonus_percentage => 0.15, p_bonus_amount => v_amount, p_status => v_status);
DBMS_OUTPUT.PUT_LINE('状态: ' || v_status || ', 奖金金额: ' || v_amount);
END;
/
1.3 包(Package)的完整支持
包是Oracle PL/SQL中用于封装相关函数、过程、变量的大型代码单元。KES对此有完整的支持。
sql
-- 示例3:创建包规范(Package Specification)
CREATE OR REPLACE PACKAGE pkg_employee_mgmt AS
-- 声明常量
g_max_salary CONSTANT NUMBER := 100000;
-- 声明游标
CURSOR cur_high_paid_emps RETURN employees%ROWTYPE;
-- 声明函数和过程
FUNCTION get_avg_salary(p_dept_id NUMBER) RETURN NUMBER;
PROCEDURE update_employee_salary(p_emp_id IN NUMBER, p_new_salary IN NUMBER, p_rows_affected OUT NUMBER);
END pkg_employee_mgmt;
/
-- 创建包体(Package Body)
CREATE OR REPLACE PACKAGE BODY pkg_employee_mgmt AS
-- 实现游标
CURSOR cur_high_paid_emps RETURN employees%ROWTYPE IS
SELECT * FROM employees WHERE salary > 50000;
-- 实现函数(使用聚集函数)
FUNCTION get_avg_salary(p_dept_id NUMBER) RETURN NUMBER IS
v_avg_sal NUMBER;
BEGIN
SELECT AVG(salary) INTO v_avg_sal
FROM employees
WHERE department_id = p_dept_id;
RETURN NVL(v_avg_sal, 0); -- 使用NVL函数处理空值
END get_avg_salary;
-- 实现过程(进行数据更新)
PROCEDURE update_employee_salary(p_emp_id IN NUMBER, p_new_salary IN NUMBER, p_rows_affected OUT NUMBER) IS
BEGIN
IF p_new_salary > g_max_salary THEN
RAISE_APPLICATION_ERROR(-20001, '薪资超过上限' || g_max_salary); -- 使用自定义异常
END IF;
UPDATE employees
SET salary = p_new_salary
WHERE employee_id = p_emp_id;
p_rows_affected := SQL%ROWCOUNT; -- 获取影响行数
IF p_rows_affected = 0 THEN
RAISE NO_DATA_FOUND;
END IF;
END update_employee_salary;
END pkg_employee_mgmt;
/
-- 使用包中的功能
BEGIN
DBMS_OUTPUT.PUT_LINE('部门平均薪资: ' || pkg_employee_mgmt.get_avg_salary(10));
END;
/
二、超越兼容:金仓KES对现代数据格式(JSON)的强大支持

除了对传统PL/SQL的兼容,金仓KES也紧跟技术发展趋势,提供了对JSON数据类型的原生支持和丰富的JSON函数,使其能够轻松应对半结构化数据处理场景。
2.1 JSON数据的存储与基本查询
KES提供了JSON数据类型来高效存储JSON文档。
sql
-- 示例4:创建包含JSON列的表并插入数据(增)
CREATE TABLE product_catalog (
product_id NUMBER PRIMARY KEY,
product_info JSON, -- 使用JSON类型
create_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
-- 插入JSON数据
INSERT INTO product_catalog (product_id, product_info) VALUES (
1,
'{
"name": "智能手机",
"brand": "华为",
"specs": {"screen": "6.5inch", "memory": "8GB", "storage": "256GB"},
"price": 5999.00,
"in_stock": true,
"tags": ["5G", "徕卡镜头", "快充"]
}'
);
INSERT INTO product_catalog (product_id, product_info) VALUES (
2,
'{"name": "平板电脑", "brand": "苹果", "price": 4999.00, "in_stock": false}'
);
-- 基本查询:使用 -> 操作符提取JSON键值(查)
SELECT product_id, product_info -> 'name' as product_name, product_info -> 'price' as price
FROM product_catalog;
2.2 高级JSON函数与路径查询
KES支持丰富的JSON函数,如json_extract_path_text, jsonb_set, json_array_elements等,用于复杂操作。
sql
-- 示例5:使用路径查询和函数处理JSON
-- 查询特定路径下的值
SELECT
product_id,
json_extract_path_text(product_info::jsonb, 'specs', 'memory') as memory_size, -- 提取嵌套值
product_info -> 'tags' as tags_array
FROM product_catalog
WHERE product_info -> 'brand' = '"华为"'; -- 注意JSON字符串的引号
-- 使用 json_table 将JSON数据解析为关系表格式(强大的行转换)
SELECT p.product_id, jt.*
FROM product_catalog p,
JSON_TABLE(p.product_info, '$'
COLUMNS (
name VARCHAR(100) PATH '$.name',
brand VARCHAR(50) PATH '$.brand',
price NUMBER PATH '$.price',
in_stock BOOLEAN PATH '$.in_stock'
)
) AS jt;
-- 更新JSON文档中的特定字段(改)
UPDATE product_catalog
SET product_info = jsonb_set(product_info::jsonb, '{price}', '5499.00'::jsonb) -- 修改价格
WHERE product_id = 1;
-- 向JSON数组添加元素(增)
UPDATE product_catalog
SET product_info = jsonb_insert(product_info::jsonb, '{tags, 0}', '"新品"') -- 在tags数组开头插入"新品"
WHERE product_id = 2;
-- 删除JSON中的某个键(删)
UPDATE product_catalog
SET product_info = product_info::jsonb - 'in_stock' -- 删除in_stock键
WHERE product_id = 2;
三、内置函数、聚集函数与分析函数对比

KES在函数方面也力求与Oracle对齐,减少了迁移过程中的代码重写工作。
| 函数类别 | Oracle示例 | 金仓KES兼容情况 | 备注 |
|---|---|---|---|
| 内置函数 | TO_CHAR(sysdate, 'YYYY-MM-DD') NVL(salary, 0) DECODE(status, 'A', 1, 'B', 2, 0) |
高度兼容 | KES支持绝大部分Oracle常用内置函数,DECODE函数得到完全支持。 |
| 聚集函数 | AVG(salary) COUNT(DISTINCT dept_id) LISTAGG(name, ',') WITHIN GROUP (ORDER BY id) |
高度兼容 | 标准聚集函数完全兼容。LISTAGG等高级聚集函数在KES中同样可用。 |
| 分析函数 | ROW_NUMBER() OVER (PARTITION BY dept ORDER BY salary DESC) LAG(salary, 1) OVER (ORDER BY hire_date) SUM(salary) OVER (PARTITION BY dept_id) |
高度兼容 | KES对Oracle分析函数(窗口函数)的支持非常完善,语法完全一致,是复杂报表查询平滑迁移的保障。 |
sql
-- 示例6:分析函数实战 - 计算部门内薪资排名与累计薪资
SELECT
employee_id,
employee_name,
department_id,
salary,
-- 计算部门内薪资排名
ROW_NUMBER() OVER (PARTITION BY department_id ORDER BY salary DESC) as dept_salary_rank,
-- 计算部门内薪资累计(从最低到当前行)
SUM(salary) OVER (PARTITION BY department_id ORDER BY salary ROWS UNBOUNDED PRECEDING) as dept_cumulative_salary,
-- 获取部门平均薪资
AVG(salary) OVER (PARTITION BY department_id) as dept_avg_salary
FROM employees
ORDER BY department_id, salary DESC;
总结与建议
通过以上深入的代码演示和分析,我们可以清晰地看到,电科金仓的KES数据库在PL/SQL兼容性方面确实下足了功夫,能够有效支撑从Oracle数据库的平滑迁移:
-
PL/SQL核心语法高兼容:从基础块、游标、异常到包管理等高级特性,KES提供了企业级的支持,保障了核心业务逻辑的复用。
-
现代数据处理能力:对JSON等半结构化数据的原生支持,使KES不仅能承接传统应用,还能满足现代应用开发的新需求。
-
全面的函数支持:内置函数、聚集函数、分析函数的广泛兼容,确保了SQL脚本和复杂查询的顺利迁移。

迁移实践建议:
-
评估阶段 :使用电科金仓 提供的KDTS 或KDMS迁移评估工具,对现有Oracle代码进行自动化兼容性评估,精准识别需修改的少量代码点。
-
测试阶段 :在KES环境中进行充分的单元测试和集成测试,重点关注涉及复杂业务逻辑的存储过程和函数。
-
性能调优 :利用KES 的RWC 读写分离集群或Sharding分库分表组件,对迁移后的应用进行针对性的性能优化。
数据库国产化替代是一项复杂的系统工程,选择一款在技术生态上高度兼容、在产品能力上持续创新的数据库至关重要。电科金仓KES凭借其在Oracle兼容性方面的深厚积累和对现代数据架构的支撑能力,无疑是企业实现安全、平滑、高效迁移的可靠选择。

关于本文,博主还写了相关文章,欢迎关注《电科金仓》分类:
第一章:基础与入门(13篇)
1、【金仓数据库征文】政府项目数据库迁移:从MySQL 5.7到KingbaseES的蜕变之路
2、【金仓数据库征文】学校AI数字人:从Sql Server到KingbaseES的数据库转型之路
3、电科金仓2025发布会,国产数据库的AI融合进化与智领未来
5、《一行代码不改动!用KES V9 2025完成SQL Server → 金仓"平替"迁移并启用向量检索》
6、《赤兔引擎×的卢智能体:电科金仓如何用"三骏架构"重塑AI原生数据库一体机》
7、探秘KingbaseES在线体验平台:技术盛宴还是虚有其表?
9、KDMS V4 一键搞定国产化迁移:零代码、零事故、零熬夜------金仓社区发布史上最省心数据库迁移评估神器
10、KingbaseES V009版本发布:国产数据库的新飞跃
11、从LIS到全院云:浙江省人民医院用KingbaseES打造国内首个多院区异构多活信创样板
12、异构多活+零丢失:金仓KingbaseES在浙人医LIS国产化中的容灾实践
13、金仓KingbaseES数据库:迁移、运维与成本优化的全面解析
第二章:能力与提升(10篇)
1、零改造迁移实录:2000+存储过程从SQL Server滑入KingbaseES V9R4C12的72小时
3、在Ubuntu服务器上安装KingbaseES V009R002C012(Orable兼容版)数据库过程详细记录
4、金仓数据库迁移评估系统(KDMS)V4 正式上线:国产化替代的技术底气
5、Ubuntu系统下Python连接国产KingbaseES数据库实现增删改查
7、Java连接电科金仓数据库(KingbaseES)实战指南
8、使用 Docker 快速部署 KingbaseES 国产数据库:亲测全过程分享
9、【金仓数据库产品体验官】Oracle兼容性深度体验:从SQL到PL/SQL,金仓KingbaseES如何无缝平替Oracle?
10、KingbaseES在Alibaba Cloud Linux 3 的深度体验,从部署到性能实战
第三章:实践与突破(13篇)
2、【金仓数据库产品体验官】实战测评:电科金仓数据库接口兼容性深度体验
3、KingbaseES与MongoDB全面对比:一篇从理论到实战的国产化迁移指南
4、从SQL Server到KingbaseES:一步到位的跨平台迁移与性能优化指南
5、ksycopg2实战:Python连接KingbaseES数据库的完整指南
6、KingbaseES:从MySQL兼容到权限隔离与安全增强的跨越
7、电科金仓KingbaseES数据库全面语法解析与应用实践
8、电科金仓国产数据库KingBaseES深度解析:五个一体化的技术架构与实践指南
9、电科金仓自主创新数据库KingbaseES在医疗行业的创新实践与深度应用
11、金仓数据库引领新能源行业数字化转型:案例深度解析与领导力展现
13、Oracle迁移实战:从兼容性挑战到平滑过渡金仓数据库的解决方案
第四章:重点与难点(13篇)
1、从Oracle到金仓KES:PL/SQL兼容性与高级JSON处理实战解析
后期作品正在准备中,敬请关注......