暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

金仓数据库 Oracle 兼容模式再体验

原创 严少安 2025-09-30
676

9 月的体验官活动已结束,10 月新一期金仓数据库产品体验官活动开启了,本期主题是“接口多兼容深度体验”。本期内容偏开发,实战型很强,建议大家提前着手准备。

#KINGBASE 如果你还没有金仓社区的账号,欢迎注册:https://bbs.kingbase.com.cn/register
记得填写邀请人:18185

前几期内容参考如下:

正文开始。

准备数据库

本文使用的是 KingbaseES V009R001C010 的 Oracle 兼容模式,其他不多介绍。

kingbase# select version();
         version
-------------------------
 KingbaseES V009R001C010
(1 row)

kingbase# show database_mode;
 database_mode
---------------
 oracle
(1 row)

接下来介绍两个兼容点,以供参考。

LATERAL 连接

在 Oracle 中,LATERAL 关键字用于在查询中引用外部查询的列。它允许在子查询中使用外部查询的结果,从而实现更灵活的数据处理。

金仓数据库在 Oracle 兼容模式里 1:1 还原了语义,用户可直接使用 Oracle 的语法。

常见用法

LATERAL 主要用于关联子查询和处理复杂数据结构两个场景。

关联子查询

当子查询需要引用外部查询的列时,使用 LATERAL 可以使子查询能够访问外部查询的结果,实现关联查询。

假设有两个表:departments(部门表)和 employees(员工表),现在需要查询每个部门中工资最高的员工信息。

-- 创建示例表 CREATE TABLE departments ( dept_id NUMBER PRIMARY KEY, dept_name VARCHAR2(100) ); CREATE TABLE employees ( emp_id NUMBER PRIMARY KEY, emp_name VARCHAR2(100), salary NUMBER, dept_id NUMBER ); -- 插入示例数据 INSERT INTO departments (dept_id, dept_name) VALUES (1, 'HR'); INSERT INTO departments (dept_id, dept_name) VALUES (2, 'IT'); INSERT INTO employees (emp_id, emp_name, salary, dept_id) VALUES (1, 'Alice', 5000, 1); INSERT INTO employees (emp_id, emp_name, salary, dept_id) VALUES (2, 'Bob', 6000, 1); INSERT INTO employees (emp_id, emp_name, salary, dept_id) VALUES (3, 'Charlie', 7000, 2); INSERT INTO employees (emp_id, emp_name, salary, dept_id) VALUES (4, 'David', 8000, 2); -- 查询每个部门中工资最高的员工信息 SELECT d.dept_name, e.emp_name, e.salary FROM departments d, LATERAL ( SELECT emp_name, salary FROM employees WHERE dept_id = d.dept_id ORDER BY salary DESC FETCH FIRST 1 ROWS ONLY ) e;

结果输出:

 dept_name | emp_name | salary
-----------+----------+--------
 HR        | Bob      |   6000
 IT        | David    |   8000
(2 rows)

处理复杂数据结构

在处理包含数组、嵌套表等复杂数据结构时,LATERAL 可以将这些结构展开,方便进行数据处理和分析。

需要注意的是,虽然 LATERAL 提供了强大的查询能力,无需再写 ROW_NUMBER() OVER (PARTITION BY ...) 那一大坨,但过度使用可能会导致性能下降。因为 LATERAL 子查询会为外部查询的每一行执行一次,所以在处理大量数据时需要谨慎使用。语法方面,LATERAL 关键字必须紧跟在子查询之前,并且子查询必须是一个表子查询。

select 语句 bulk collect into 子句

Oracle DBA 熟悉的 PL/SQL 批量取数语法,在金仓数据库中也支持了。

演示案例,创建测试表、准备数据。

create table test (
id number primary key,
val varchar2(20),
something_else varchar2(20));

insert into test (id, val, something_else) values (1,'test1','else');
insert into test (id, val, something_else) values (2,'test2','else');
insert into test (id, val, something_else) values (3,'test3','else');
insert into test (id, val, something_else) values (4,'test4','else');

运行匿名块,脚本零修改,直接跑通,无报错。

kingbase# DECLARE
kingbase-#    CURSOR test_cur
kingbase-#    IS
kingbase-#          SELECT
kingbase-#             id,
kingbase-#             val
kingbase-#          FROM
kingbase-#             test
kingbase-#    ;
kingbase-# type test_rt
kingbase-# IS
kingbase-#    record
kingbase-#    (
kingbase(#       id test.id%type,
kingbase(#       val test.val%type);
kingbase-#    type test_rec_arr is table of test_rt index by pls_integer;
kingbase-#    test_rec test_rec_arr;
kingbase-# BEGIN
kingbase-#    OPEN test_cur;
kingbase-#    LOOP
kingbase-#       FETCH
kingbase-#          test_cur bulk collect
kingbase-#       INTO
kingbase-#          test_rec limit 10;
kingbase-#       NULL;
kingbase-#       EXIT
kingbase-#    WHEN test_rec.count = 0;
kingbase-#    END LOOP;
kingbase-#    CLOSE test_cur;
kingbase-# END;
kingbase-# /
ANONYMOUS BLOCK

总结

Oracle 语法兼容性是个系统工程,需要智力和体力,不是一朝一夕就能完成的,尤其是很多语法细节的处理,需要在更多场景下验证。下节内容,我们开始介绍金仓数据库的接口,看看换成金仓数据库后,代码零修改能否真的让程序跑起来。

Have a nice day ~ ☕


🌻 往期精彩 ▼

– / END / –

👉 欢迎关注我的视频号

👉 这里有得聊

如果对国产基础软件(操作系统、数据库、中间件)感兴趣,可以加群一起聊聊。
关注微信公众号:少安事务所,后台回复[群],即可看到入口。

如果这篇文章为你带来了灵感或启发,请帮忙『三连』吧,感谢!ღ( ´・ᴗ・` )~

「喜欢这篇文章,您的关注和赞赏是给作者最好的鼓励」
关注作者
【版权声明】本文为墨天轮用户原创内容,转载时必须标注文章的来源(墨天轮),文章链接,文章作者等基本信息,否则作者和墨天轮有权追究责任。如果您发现墨天轮中有涉嫌抄袭或者侵权的内容,欢迎发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

文章被以下合辑收录

评论