【IT168 专稿】Oracle作为目前市场业内知名的数据库管理系统,已广泛应用于各个行业领域。为了方便基于Oracle的应用向新一代达梦数据库DM7移植,减轻开发人员的工作量,DM7做了大量的Oracle兼容性工作。
本文主要介绍包、CONNECT BY层次查询和ROWNUM三个主要的兼容特性。
(一)包(package)的兼容
包类似于存储过程,可将过程说明和过程体组成一个程序单位。也可将过程说明与它的过程体分开,在这种情况下,将过程放置在一个包中,可隐蔽实现的细节。也可在包中定义过程,而该过程在包说明中没有定义过程说明,这样定义的过程仅在包内使用。包可以编译、存贮在数据库中,其内容可为许多应用共享。当用户第一次调用包中的子程序时,整个包都会被装载到内存,所以在以后对包中子程序调用时,不再需要I/O操作,故包可提高效率和改进性能。对于一个复杂的应用系统来说,包功能提供了一个巨大的便利,在系统中可以按照功能模块划分,把同一个模块的TYPE、FUNCTION、PROCEDURE放在一起,这样既方便数据库开发人员的维护更新,也方便了应用系统开发人员的调用。
在ORACLE数据库中,包和类型(Type)、过程(Procedure)、函数(Function)等一样都是PL/SQL的对象。不同的是,包(Package)更像是一个结构,将逻辑上相关的PL/SQL类型、对象和子程序组合成一个更大的单位。包有两个部分:包定义(specification)和包体(body)。说明部分是为应用程序的接口,它申明类型、常量、例外、游标和可用的子程序。包体定义游标、子程序和实现说明。
在DM7中,我们从整体结构和语法上实现了与Oracle一致的Package,包括包头与包体的定义、调用方式、以及内部变量声明方式与作用域和生命周期。下面给出一个简单的包括包定义、包体、类型、过程和函数的完整的package定义样例:
name varchar(50),
publishtime date,
price number,
author varchar(50));
insert into book values(1, '系统管理员手册', '2011-08-01', 70.00, 'JOE');
insert into book values(2, '程序员手册', '2011-08-01', 60.00, 'GYAN');
create or replace package product_info
as
type info is record
(
id int,
name varchar(10),
publishtime date,
price number
);
type product_cur is ref cursor return info;
procedure get_author(idvar in int,authorvar out varchar(50));
function get_publisher(namevar in varchar(50)) return info;
end product_info;
create or replace package body product_info
as
procedure get_author(idvar in int,authorvar out varchar(50))
is
begin
select author into authorvar from book where id=idvar;
end get_author;
function get_publisher(namevar in varchar(50)) return info
as
prod_cur product_cur;
prod_info info;
begin
open prod_cur for select id,name,publishtime,price from book
where name=namevar;
loop
exit when prod_cur%notfound;
fetch prod_cur into prod_info;
DBMS_output.put_line(prod_info.id || ' ' || prod_info.name
|| ' ' || prod_info.publishtime || ' ' || prod_info.price);
end loop;
close prod_cur;
end get_publisher;
end product_info;
select product_info.get_publisher('系统管理员手册');
可以看出,DM7支持了大量Oracle专有的PL/SQL语法,如引用游标、用户自定义类型、DBMS_OUTPUT包、循环语句LOOP等。需要注意的是,用户如果要引用DBMS_OUTPUT包,需要先执行DM7安装目录中的DBMS_OUTPUT包安装脚本文件。
(二)CONNECT BY层次查询兼容
Oracle层次查询对于需要查询具有树状层次关系的应用具有较大的实际应用价值。DM7中提供了对CONNECT BY层次查询的兼容,支持start with、order siblings by子句,支持PRIOR、CONNECT_BY_ROOT操作符,支持nocycle环检测设置。
例如,公司中从老板到员工是分级别进行层次管理的,假设表结构为:
employee_id INT, //员工编号
emp_name VARCHAR(10), //员工姓名
title VARCHAR(15), //员工职位
manager_id INT //员工所在部门经理的编号
);
与Oracle一样,在DM7中,下面的语句可以查询出职位CEO下的所有员工的名字、职位和其经理的名字。
FROM employee
CONNECT BY PRIOR employee_id = manager_id
START WITH title = ‘CEO’;
(三)ROWNUM兼容
ROWNUM是一个Oracle查询中的一个伪列,表示从表中查询的行号,或者连接查询的结果集行数。利用ROWNUM,可以生成一些原先难以实现的结果输出。DM7实现了对ROWNUM的兼容。
一般来说,ROWNUM用来控制返回结果集的规模,从这个意义上看,其作用非常类似于DM7也支持的top操作符。例如,
Select * from employee where rownum < 11; 等价于
Select top 10 * from employee;
即只返回employee表的前10行。然而,ROWNUM值的分配是在查询的谓词解析之后,任何排序和聚合之前进行的,所以rownum与top是不完全等价的。例如,
Select * from employee where rownum < 11 group by emp_name order by employee_id;等价于
Select * from (Select top 10 * from employee) group by emp_name order by employee_id;
其意义就是仅对employee表的前10行进行排序和聚合操作。
DM7除了提供了包、CONNECT BY层次查询和ROWNUM,还支持“+”外连接、函数索引、嵌套子过程/函数等诸多Oracle兼容特性。达梦公司在这些方面的工作能够大大降低Oracle平台上的开发者的学习成本,使他们从Oracle转移到DM7上进行开发的过程变得很轻松,也使得已有应用的移植变得十分容易,大大缩短了开发及测试的时间。