在Oracle数据库中,Package是一个非常重要的功能。Package功能分为包头(package)和包体(package body)两个部分,包头部分声明包内数据类型,常量,变量,游标,函数 ,存储过程和异常错误处理,这些元素为包的公有元素。包体部分则是包头部分的具体实现,它负责为包头中所声明子程序提供具体的实现,在包主体中还可以声明包的私有元素。自Halo13版本起,Halo数据库全系适配了Oracle的Package功能,本文将以现主流Halo14版本,简要演示Halo-Package的部分功能。
一、Package相关语法
1.1、Package创建语法
CREATE [ OR REPLACE ] PACKAGE package_name
[ { AUTHID DEFINER } | { AUTHID CURRENT_USER } ] -- 相关权限设置
{ IS | AS }
[ declaration; ] ... -- 此处可声明自定义类型、常量、变量、游标等
[
{ -- 存储过程声明
PROCEDURE proc_name
([ argname [ IN | IN OUT | OUT ] argtype [ DEFAULT value ] ... ]) ;
}
|
{ -- 函数声明
FUNCTION func_name ([ argname [ IN | IN OUT | OUT ] argtype [ DEFAULT value ] ... ])
RETURN rettype ;
}
] ...
END [ package_name ] ;
CREATE [ OR REPLACE ] PACKAGE BODY package_name
{ IS | AS }
[ private_declaration; ] ... -- 可定义私有常量、变量、游标、函数、存储过程等... 不对外开放供Pakcage内部使用
[
{
PROCEDURE proc_name[ {argname [ IN | IN OUT | OUT ] argtype [ DEFAULT value ] ... }]
{ IS | AS }
[ declaration; ] [, ...]
BEGIN
statement; [...]
[ EXCEPTION
{ WHEN exception [OR exception] [...]] THEN statement; }
[...]
]
END [ proc_name ] ;
}
|
{
FUNCTION func_name [ argument_list ]
RETURN rettype [DETERMINISTIC]
{ IS | AS }
[ declaration; ] [, ...]
BEGIN
statement; [...]
[ EXCEPTION
{ WHEN exception [ OR exception ] [...] THEN statement; }
[...]
]
END [ func_name ] ;
}
] ...
END [ package_name ] ;
1.2、Package移除语法
DROP PACKAGE package_name; -- 移除整个包
DROP PACKAGE BODY package_name; -- 移除当前包体
二、Package部分功能展示
2.1、常量
CREATE OR REPLACE PACKAGE PKG_CONSTANT AS
C_CODE_SUCCESS CONSTANT VARCHAR2(10) := 'SUCCESS'; -- 声明常量并赋值
PROCEDURE PRO_TEST;
END PKG_CONSTANT;
/
CREATE OR REPLACE PACKAGE BODY PKG_CONSTANT AS
PROCEDURE PRO_TEST AS
BEGIN
DBMS_OUTPUT.PUT_LINE('PKG_CONSTANT.C_CODE_SUCCESS: '||PKG_CONSTANT.C_CODE_SUCCESS);
END PRO_TEST;
END PKG_CONSTANT;
/
-- 执行
EXEC PKG_CONSTANT.PRO_TEST;
-- 常量不被允许修改 尝试修改将会报错
BEGIN
PKG_CONSTANT.C_CODE_SUCCESS := 'ERROR';
DBMS_OUTPUT.PUT_LINE('PKG_CONSTANT.C_CODE_SUCCESS: '||PKG_CONSTANT.C_CODE_SUCCESS);
END;
/
2.2、变量
CREATE OR REPLACE PACKAGE PKG_VAR AS
VAR_A VARCHAR2; -- 声明变量
PROCEDURE PRO_TEST;
END PKG_VAR;
/
CREATE OR REPLACE PACKAGE BODY PKG_VAR AS
PROCEDURE PRO_TEST AS
BEGIN
-- 初次赋值
PKG_VAR.VAR_A := 'VAR_TEST';
DBMS_OUTPUT.PUT_LINE('PKG_VAR.VAR_A: '||PKG_VAR.VAR_A);
-- 再次修改变量值
PKG_VAR.VAR_A := 'VAR_A';
DBMS_OUTPUT.PUT_LINE('PKG_VAR.VAR_A: '||PKG_VAR.VAR_A);
END PRO_TEST;
END PKG_VAR;
/
-- 执行
EXEC PKG_VAR.PRO_TEST;
2.3、游标
CREATE TABLE example(manager_id INT, employee_id INT, employee VARCHAR2(30));
INSERT INTO example VALUES(5, 1, 'Nick');
INSERT INTO example VALUES(1, 2, 'Josh');
INSERT INTO example VALUES(2, 3, 'Ali');
INSERT INTO example VALUES(6, 4, 'Joe');
INSERT INTO example VALUES(4, 5, 'Kyle');
CREATE OR REPLACE PACKAGE PKG_CURSOR
AS
TYPE PKG_TYPE_CURSOR IS REF CURSOR;
PROCEDURE PRO_TEST;
END PKG_CURSOR;
/
CREATE OR REPLACE PACKAGE BODY PKG_CURSOR
AS
PROCEDURE PRO_TEST
IS
cur_cursor PKG_TYPE_CURSOR;
cur_val example%ROWTYPE;
BEGIN
OPEN cur_cursor FOR SELECT * FROM example;
LOOP
FETCH cur_cursor INTO cur_val;
EXIT WHEN NOT FOUND;
DBMS_OUTPUT.PUT_LINE('manager_id: '||cur_val.manager_id||' employee_id: '||cur_val.employee_id||' employee: '||cur_val.employee);
END LOOP;
CLOSE cur_cursor;
END PRO_TEST;
END PKG_CURSOR;
/
-- 执行
EXEC PKG_CURSOR.PRO_TEST
2.4、函数和存储过程
CREATE OR REPLACE PACKAGE PKG_TEST AS
FUNCTION F_TEST( f_a INTEGER , f_b INTEGER ) RETURN INTEGER;
PROCEDURE PRO_TEST;
END PKG_TEST;
/
CREATE OR REPLACE PACKAGE BODY PKG_TEST AS
FUNCTION F_TEST( f_a IN INTEGER , f_b IN INTEGER )
RETURN INTEGER
AS
f_c INTEGER;
BEGIN
f_c := f_a + f_b;
RETURN f_c;
END F_TEST;
PROCEDURE PRO_TEST
AS
var_a INTEGER;
BEGIN
var_a := PKG_TEST.F_TEST(12,13);
DBMS_OUTPUT.PUT_line('PKG_TEST.F_TEST(12,13) = '|| var_a);
END PRO_TEST;
END PKG_TEST;
/
2.5、自定义类型
CREATE OR REPLACE PACKAGE PKG_RECODE_TEST AS
TYPE RECODE_TYPE IS RECORD(
DS NUMBER(10, 3),
DA VARCHAR(2)
);
PROCEDURE PRO_TEST;
END PKG_RECODE_TEST;
/
CREATE OR REPLACE PACKAGE BODY PKG_RECODE_TEST AS
PROCEDURE PRO_TEST
AS
recode_a RECODE_TYPE;
BEGIN
SELECT 1,'x' INTO recode_a FROM dual;
DBMS_OUTPUT.PUT_line(recode_a.ds||' '||recode_a.da);
END PRO_TEST;
END PKG_RECODE_TEST;
/
-- 执行
EXEC PKG_RECODE_TEST.PRO_TEST;
2.6、异常
CREATE OR REPLACE PACKAGE ERRLOG
IS
no_such_table EXCEPTION;
PRAGMA EXCEPTION_INIT (no_such_table, -942);
invalid_table_name EXCEPTION;
PRAGMA EXCEPTION_INIT (invalid_table_name, -903);
PROCEDURE PRO_TEST;
END;
/
CREATE OR REPLACE PACKAGE BODY ERRLOG AS
PROCEDURE PRO_TEST
AS
BEGIN
RAISE ERRLOG.no_such_table;
DBMS_OUTPUT.PUT_LINE('ERROR');
EXCEPTION
WHEN no_such_table THEN
DBMS_OUTPUT.PUT_LINE('SQLCODE: '||SQLCODE||' SQLERRM: '||SQLERRM);
END PRO_TEST;
END ERRLOG;
/
-- 执行
EXEC ERRLOG.PRO_TEST;
三、注意事项
3.1、 无法正常结束,进入$状态
检查是以psql还是以hsql连接的数据库,如果是以psql连接的数据库,有两种处理方式,一种是采用\q退出连接,然后通过hsql连接数据库,另一种方式检查参数ENABLE_PL_BLOCK是否为on,如不为on,采用下面命令。一般情况下,如无需使用PG的sql语法,建议使用hsql连接管理数据库。
\set -- 查看ENABLE_PL_BLOCK参数
\set ENABLE_PL_BLOCK on -- 使能ENABLE_PL_BLOCK
人物A 回复
这是回复
人物B 回复
我回复你了
人物A 回复
回复已收到