更新时间:2024-11-12 GMT+08:00
分享

CREATE PACKAGE

功能描述

创建一个新的PACKAGE。

注意事项

  • 在分布式下,PACKAGE仅支持在ORA兼容性数据库中使用。
  • 在package specification中声明过的函数或者存储过程,必须在package body中找到定义。
  • 创建存储过程时,仅对CREATE的存储过程或PACKAGE本身加写锁,仅对执行过程中编译、执行会对函数和函数依赖的PACKAGE均加读锁。
  • 在实例化中,无法调用带有commit/rollback的存储过程。
  • 不能在Trigger中调用package函数。
  • 不能在外部SQL中直接使用package当中的变量。
  • 不允许在package外部调用package的私有变量和存储过程。
  • 不支持存储过程不支持的用法,例如,在function中不允许调用commit/rollback,则package的function中同样无法调用commit/rollback。
  • 不支持schema与package同名。
  • 只支持ORA风格的存储过程和函数定义。
  • 不支持package内有同名变量,包括包内同名参数。
  • package的全局变量为session级,不同session之间package的变量不共享。
  • package中调用自治事务的函数,不允许使用package中的cursor变量,以及不允许递归的使用package中cursor变量的函数。
  • package中不支持声明ref cursor变量。
  • package默认为SECURITY INVOKER权限,如果想将默认行为改为SECURITY DEFINER权限,需要设置guc参数behavior_compat_options='plsql_security_definer'。
  • 被授予CREATE ANY PACKAGE权限的用户,可以在public模式和用户模式下创建PACKAGE。
  • 如果需要创建带有特殊字符的package名,特殊字符中不能含有空格,并且最好设置GUC参数behavior_compat_options="skip_insert_gs_source",否则可能引起报错。
  • 创建package函数时,其参数默认值支持含有package内变量,不支持跨package变量。
  • package中函数复杂调用,如:func(x).a,函数调用返回复合类型,支持跨schema调用,不支持通过database.schema.package.func(x).b的方式调用。
  • 在创建package内的存储过程时,如果存储过程名称为schema.func或package.func形式,只会获取func的名称,schema声明或package声明无效,如果需要默认禁止这种行为,可以设置GUC参数behavior_compat_options='forbid_package_function_with_prefix'。
  • 不支持view%rowtype作为函数参数。
  • 不支持存储过程/函数中insert values使用复合类型record。
  • 分布式不支持SAVE EXCEPTIONS(调用的存过中使用)。

  • 表达式不支持commit/rollback。
  • 无参function不支持省略括号。

  • 自定义类型变量不支持下推。

  • 在创建PACKAGE内的存储过程时,如果存储过程的入参包含伪类型(如:anyelement),不支持调用时传入变长类型的参数。
  • package内创建的游标或者函数带参数游标,可以跨package进行类型引用(%RowType)和打开使用,有以下限制:
    1. 暂不支持通过database.schema.package.cursor的方式调用游标。
    2. 分布式不支持将游标定义为函数参数。
    3. 当引用游标时,不支持cursor%RowType。

语法格式

  • CREATE PACKAGE SPECIFICATION语法格式。
    CREATE [ OR REPLACE ] PACKAGE [ schema ] package_name
        [ invoker_rights_clause ] { IS | AS } item_list_1 END [ package_name ];

    • invoker_rights_clause可以被声明为AUTHID DEFINER或者AUTHID CURRENT_USER,分别为定义者权限和调用者权限。
    • item_list_1可以为声明的变量或者存储过程以及函数。
    • END后的package_name可省略(gs_dump生成的sql文件,PACKAGE定义会自动补上END后名称)。

    PACKAGE SPECIFICATION(包头)声明了包内的公有变量、函数、异常等,可以被外部函数或者存储过程调用。在PACKAGE SPECIFICATION中只能声明存储过程、函数,不能定义存储过程或者函数。

  • CREATE PACKAGE BODY语法格式。
    CREATE [ OR REPLACE ] PACKAGE BODY [ schema ] package_name
        { IS | AS } declare_section [ initialize_section ] END [ package_name ];

    END后的package_name可省略(gs_dump生成的sql文件,PACKAGE定义会自动补上END后名称)。

    PACKAGE BODY(包体内)定义了包的私有变量、函数等。如果变量或者函数没有在PACKAGE SPECIFICATION中声明过,那么这个变量或者函数则为私有变量或者私有函数。

    PACKAGE BODY也可以声明实例化部分,用来初始化package,详见示例。

示例

  • CREATE PACKAGE示例
    --创建数据库。
    gaussdb=# CREATE DATABASE test DBCOMPATIBILITY 'ORA';
    gaussdb=# \c test
    
    --创建测试表tbl_test。
    test=# CREATE TABLE tbl_test(uid varchar(6) PRIMARY KEY, area_id varchar(5), level int);
    
    --创建包头。
    test=# CREATE OR REPLACE PACKAGE pkg_test AS 
        --公有存储过程可以被外部调用。
        PROCEDURE proc_ist_tbl_test(v_uid in varchar, v_area_id varchar, v_level int);  
        PROCEDURE proc_del_tbl_test(v_uid in varchar);
        PROCEDURE proc_upd_tbl_test(v_uid in varchar, v_area_id varchar, v_level int);
    END pkg_test; 
    /
    
    --创建包体。
    test=# CREATE OR REPLACE PACKAGE BODY pkg_test AS 
        PROCEDURE proc_ist_tbl_test(v_uid in varchar, v_area_id varchar, v_level int) AS
        BEGIN
            INSERT INTO tbl_test VALUES (v_uid, v_area_id, v_level);
        END;    
        PROCEDURE proc_del_tbl_test(v_uid in varchar) AS 
        BEGIN 
            DELETE FROM tbl_test WHERE uid = v_uid;
        END;
        PROCEDURE proc_upd_tbl_test(v_uid in varchar, v_area_id varchar, v_level int) AS
        BEGIN 
            UPDATE tbl_test SET area_id = v_area_id, level = v_level WHERE uid = v_uid;
        END;
        var4 int := 10;
        --实例化开始。
    BEGIN 
        var4 := 10;
        dbe_output.print_line(var4);
    END pkg_test; 
    /
  • 调用PACKAGE示例
    --使用CALL调用PACKAGE的存储过程。
    test=# CALL pkg_test.proc_ist_tbl_test('0A00B1','01001',24);
    test=# SELECT * FROM tbl_test;
      uid   | area_id | level 
    --------+---------+---------
     0A00B1 | 01001   |      24
    (1 row)
    
    --使用SELECT调用PACKAGE的存储过程。
    test=# SELECT pkg_test.proc_upd_tbl_test('0A00B1','01001','26');
    test=# SELECT * FROM tbl_test;
      uid   | area_id | level 
    --------+---------+-------
     0A00B1 | 01001   |    26
    (1 row)
    
    --匿名块调用PACKAGE的存储过程。
    test=# BEGIN 
    pkg_test.proc_del_tbl_test('0A00B1'); 
    END; 
    /
    test=# SELECT * FROM tbl_test;
     uid | area_id | level 
    -----+---------+-------
    (0 rows)
    
    --删除。
    test=# DROP TABLE tbl_test;
    test=# DROP PACKAGE pkg_test;
    --切换至默认数据库并删除test数据库(请根据实际情况修改数据库名)。
    test=# \c postgres
    gaussdb=# DROP DATABASE test;

相关文档