技术分享|GBase 8a数据库对象管理-存储过程&函数

存储过程是一组可以完成特定功能的SQL语句集,经编译后存储在数据库中。用户在执行存储过程时,需要指定存储过程的名称并给出参数(如果存储过程里包含参数)。

在如下情况中,存储过程非常有用:

l 当多个客户端应用程序是由不同的语言编写,或者运行在不同的平台,但需要执行同样的数据库操作时;

l 当安全非常重要时。例如,银行对所有常用的操作都使用存储过程。这提供了一个一致的和安全的环境,并且存储过程可以保证每一个操作都正确的写入日志。如此设置,应用程序和用户将不能直接访问数据表,只能执行特定的存储过程;

l 存储过程可以提高性能,这是因为只需要在服务器和客户端之间传递更少的信息。负面影响是增加了数据库服务器的负担,因为在服务器端执行更多的任务而在客户端(应用程序)则只需执行较少的任务。

l 存储过程允许用户在数据库服务器中使用函数库。这正是现代应用程序语言具有的特性,例如,通过使用类来进行程序设计。这些客户端应用程序语言特性不论是否应用于数据库端的设计,对程序员来说采用这样的方法还是很有益处的。

创建存储过程/函数

功能说明

存储过程和函数是由CREATE PROCEDURE和CREATE FUNCTION语句所创建的程序。

l 存储过程通过CALL语句来调用,而且只能通过输出变量得到返回值。函数可以像其它函数一样从语句内部来调用(通过调用函数名),并返回一个标量值。存储程序(过程和函数)也可以调用其它存储程序(过程和函数);

l 每个存储过程或函数都与一个特定的数据库相联系。当存储程序(过程和函数)被调用时,隐含的USE database_name被执行(当存储程序(过程和函数)结束时完成),不允许在存储程序(过程和函数)中使用USE语句。用户能使用数据库名来限定存储程序(过程和函数)名。这可以用来指明不在当前数据库中的存储程序(过程和函数)。例如,要调用一个与gbase数据库相关联的存储过程p或函数f,用户可以使用CALL gbase.p()或gbase.f()。当一个数据库被删除了,所有与它相关的存储程序(过程和函数)也都被删除了;

l GBase 8a MPP Cluster可以在存储过程中使用标准的SELECT语句。这样,一个查询的结果简单直接地传送到客户端。多个SELECT语句产生多个结果集,所以客户端必须使用一个支持多结果集的GBase 8a MPP Cluster客户端库;

l 要创建一个存储程序(过程和函数),必须具有CREATE ROUTINE权限。如果用户创建了PROCEDURE | FUNCTION,那么会自动赋予用户对该PROCEDURE | FUNCTION的ALTER ROUTINE和EXECUTE权限者。如果开启更新日志,用户可能需要SUPER权限;

l 在默认情况下,存储程序(过程和函数)与当前的数据库相关联。要显式的将过程与数据库联系起来,那用户创建存储程序(过程和函数)时需要将它的名字的格式写为vc_name.database_name.sp_name;

l 在括号中必须要有参数列表。如果没有参数,应该使用空的参数列表();默认参数为IN参数。如果要将一个参数指定为其它类型,则请在参数名前指定参数类型;

l 使用RETURNS子句(只有FUNCTION才能指定RETURNS子句)指明函数的返回类型时,函数体中必须包含一个RETURN语句;

l 如果一个存储过程或函数对同样的输入参数得到同样的结果,则被认为它是"确定的"(DETERMINISTIC),否则就是"非确定"的(NOT DETERMINISTIC)。默认是NOT DETERMINISTIC;

l 就复制来说,使用NOW()函数(或它的同义字)或RAND()并不会生成一个非确定性程序。对于NOW(),更新日志包括时间戳并能进行正确的复制。如果在一个程序中只调用一次,RAND()也能正确地复制;

l 当前DETERMINISTIC特性是可接受的,但并不被优化器所使用。然而,如果更新日志被激活,这个特性将影响到GBase 8a MPP Cluster是否接受过程的定义;

l 以下几个特征参数提供了程序的数据使用信息:

l SQL SECURITY参数用来指明,此程序的执行权限是赋予创建者还是调

l 用者。默认的值是DEFINER。创建者和调用者必须要有对与程序相关的数据库的访问权。要执行存储程序(过程和函数)必须具有EXECUTE权限,必须具有这个权限的用户要么是定义者,要么是调用者,这依赖于如何设置SQL SECURITY特征;

l COMMENT语句是GBase 8a MPP Cluster的扩展,可以用来描述存储过程。可以使用SHOW CREATE PROCEDURE、SHOW CREATE FUNCTION语句来显示这些信息。

l GBase 8a MPP Cluster允许存储程序(过程和函数)包含DDL语句(比如CREATE和DROP)和SQL事务语句(比如COMMIT)。这不是标准所需要的,只是特定的实现;

l 返回结果集的语句不能用在函数中。这些语句包括不使用INTO将列值赋给变量的SELECT语句,SHOW语句等。对于在函数定义时就返回结果集的语句返回一个“Not allowed to return a result set from a function”错误(ER_SP_NO_RETSET_IN_FUNC)。对于在函数运行时才返回结果集的语句,返回“PROCEDURE%s can't return a result set in the given context”错误(ER_SP_BADSELECT)。

语法格式

存储过程

Ø CREATE PROCEDURE ([<proc_parameter_1>[,…] [,proc_parameter_n]])

Ø [characteristic ...] routine_body

Ø CREATE FUNCTION ([<func_parameter_1>[,…] [,func_parameter_n]])

Ø RETURNS  type

[characteristic ...] routine_body

Proc_parameter:

{IN | OUT | INOUT } param_name type

Func_parameter:

Param_name type

Characteristic:

  LANGUAGE SQL

  | [NOT] DETERMINISTIC

  | { CONTAINS SQL | NO SQL | READS SQL DATA | MODIFIES SQL DATA }

  | SQL SECURITY { DEFINER | INVOKER }

  | COMMENT 'string'

 720 参数说明

字段名称

含 义 说 明

proc_name

要创建的存储过程的名称,在同一VC下,存储过程的名称必须唯一。存储过程名称只允许a~z、A~Z、0~9、下划线,且不能只包含数字。

proc_parameter

定义存储过程的参数,每一个参数的定义格式是:<参数方向><参数名称><参数数据类型>。

func_name

要创建的函数的名称,在同一VC下,函数的名称必须唯一。函数名称只允许a~z、A~Z、0~9、下划线,且不能只包含数字。

func_parameter

定义函数的参数,每一个参数的定义格式是:<参数名称><参数数据类型>。

IN | OUT | INOUT

确定参数是输入、输出还是输入输出,只能取IN、OUT、INOUT中的一个。

param_name

参数名称,在同一个存储过程/函数中必须唯一,只允许a~z、A~Z、0~9、下划线,且不能只包含数字;

type

参数数据类型,取值为GBase 8a MPP Cluster支持的数据类型

LANGUAGE SQL

说明routine_body部分是由SQL语句组成的,SQL是LANGUAGE特性的唯一值,表示当前仅支持SQL语句。

[NOT] DETERMINISTIC

指明存储过程执行的结果是否是确定的。

DETERMINISTIC 表示结果是确定的。每次执行存储过程时,相同的输入会得到相同的输出。

NOT DETERMINISTIC 表示结果是不确定的,相同的输入可能得到不同的输出。如果没有指定任意一个值,默认为NOT DETERMINISTIC

CONTAINS SQL | NO SQL | READS SQL DATA | MODIFIES SQL DATA

表示子程序使用SQL语句的限制。

CONTAINS SQL表明子程序包含SQL语句,但是不包含读写数据的语句,默认情况下,系统会指定为CONTAINS SQL;

NO SQL表明子程序不包含SQL语句;

READS SQL DATA:说明子程序包含读数据的语句;

MODIFIES SQL DATA表明子程序包含写数据的语句。

SQL SECURITY { DEFINER | INVOKER }

指明谁有权限来执行。

DEFINER 表示只有定义者才能执行,默认情况下,系统指定为DEFINER ;

INVOKER 表示拥有权限的调用者可以执行。

COMMENT ‘string’

注释信息,可以用来描述存储过程或函数

routine_body

是一系列的SQL语句的组合,其中包含一些数据操作以完成一定的功能逻辑。可以用BEGIN...END来表示SQL代码的开始和结束

说明

l 定义存储过程时,存储过程/函数时名称后面的括号是必需的,即使没有任何参数,也不能省略;

l 如果存储过程、函数中的routine_body仅包含一条SQL语句,则可以省略BEGIN和END,否则,在定义存储过程/函数时,必须使用BEGIN...END结构把相关的SQL语句组织在一起形成routine_body;

l 存储过程、函数可以嵌套。

示例

Ø 下面是一个使用IN,OUT参数的简单的存储过程的示例。这个示例在存储过程定义前,使用delimiter命令来把语句定界符从“;”变为“//”。这样就允许用在存储程序体中的“;”定界符传递到服务器,而不是被解释。

注意

l “DELIMITER //”语句的作用是将SQL的结束符设置为“//”,因为默认的语句结束符为分号“;”,为了避免与存储过程中SQL语句结束符相冲突,需要使用DELIMITER 改变存储过程的结束符,并以“END//”结束存储过程。

l 存储过程定义完毕之后再使用“DELIMITER ;”恢复默认结束符。DELIMITER 也可以指定其他符号为结束符。

Ø 示例1:创建proce_count存储过程,并调用。

gbase> DELIMITER //

gbase> CREATE PROCEDURE proc_count (OUT param1 INT,IN param2  VARCHAR(10))

     BEGIN

     SELECT COUNT(*) INTO param1 FROM ssbm.customer WHERE c_nation= param2;

     END //

Query OK, 0 rows affected

gbase> CALL proc_count(@count1,'JORDAN')//

Query OK, 0 rows affected

gbase> DELIMITER ;

gbase> SELECT @count1;

+---------+

| @count1 |

+---------+

|    1182 |

+---------+

1 row in set

说明

当使用定界符命令时,用户应该避免使用反斜杆(在GBase 8a MPP Cluster中表示转义字符)。

Ø 示例2:创建含有参数的hello函数,使用SQL函数执行操作并返回结果。

gbase> DELIMITER //

gbase> CREATE FUNCTION hello (s CHAR(20)) RETURNS CHAR(50)

     RETURN CONCAT('Hello, ',s,'!');//

Query OK, 0 rows affected

gbase> DELIMITER ;

gbase> SET @result = hello('world');

Query OK, 0 rows affected

gbase> SELECT @result;

+----------------------------------------------------+

| @result                                            |

+----------------------------------------------------+

| Hello, world               !                       |

+----------------------------------------------------+

1 row in set

说明

如果一个函数的RETURN语句返回的值与函数中RETURNS子句指明的值类型不同,返回的值强制转换为函数定义的返回值类型。

Ø 示例3:创建fn_count函数,过程定义中包含SQL语句。

gbase> DELIMITER //

gbase> CREATE FUNCTION fn_count (param  varchar(10)) RETURNS INT

       BEGIN

       SELECT COUNT(*)/5 INTO @count FROM ssbm.customer WHERE c_nation= param;

       RETURN @count;

       END//

Query OK, 0 rows affected

gbase> DELIMITER ;

 

gbase> SET @result = fn_count('JORDAN');

Query OK, 0 rows affected

gbase> SELECT @result;

+---------+

| @result |

+---------+

|     236 |

+---------+

1 row in set

修改存储过程/函数

功能说明

用来改变一个存储过程或函数的特征。用户需要有ALTER ROUTINE权限才可以使用该语句,这个权限会自动授予子程序的创建者。

语法格式

Ø ALTER {PROCEDURE | FUNCTION} [characteristic ...]

Ø characteristic:

Ø { CONTAINS SQL | NO SQL | READS SQL DATA | MODIFIES SQL DATA }

Ø SQL SECURITY { DEFINER | INVOKER }

Ø | COMMENT 'string'

 721 参数说明

参数名称

描  述

Sp_name

要修改的存储过程或函数的名称。

CONTAINS SQL | NO SQL | READS SQL DATA | MODIFIES SQL DATA

表示子程序使用SQL语句的限制。

CONTAINS SQL表明子程序包含SQL语句,但是不包含读写数据的语句,默认情况下,系统会指定为CONTAINS SQL;

NO SQL表明子程序不包含SQL语句;

READS SQL DATA:说明子程序包含读数据的语句;

MODIFIES SQL DATA表明子程序包含写数据的语句。

SQL SECURITY { DEFINER | INVOKER }

指明谁有权限来执行。

DEFINER 表示只有定义者才能执行,默认情况下,系统指定为DEFINER ;

INVOKER 表示拥有权限的调用者可以执行。

COMMENT ‘string’

注释信息,可以用来描述存储过程或函数

示例

Ø 示例1:修改存储过程的注释信息。

gbase> ALTER PROCEDURE proc_count COMMENT 'new comment';

Query OK, 0 rows affected

Ø 示例2:修改函数的注释信息。

gbase> ALTER FUNCTION fn_count COMMENT 'new comment';

Query OK, 0 rows affected

 删除存储过程/函数

功能说明

用来删除一个存储过程或函数。用户需要有ALTER ROUTINE权限才可以使用该语句,这个权限会自动授予子程序的创建者。

语法格式

Ø DROP {PROCEDURE | FUNCTION} [IF EXISTS] <sp_name>;

 722 参数说明

参数名称

描  述

IF EXISTS

如果存储过程或函数不存在,它会防止发生错误。产生一个可以用SHOW WARNINGS查看的警告。

sp_name

要删除的存储过程或函数的名称。

示例

Ø 示例1:删除存储过程。

gbase> DROP PROCEDURE IF EXISTS proc_count;

Query OK, 0 rows affected

Ø 示例2:删除函数。

gbase> DROP FUNCTION IF EXISTS fn_count;

Query OK, 0 rows affected

调用存储过程/函数

功能说明

使用CALL语句调用已经创建的存储过程。使用SELECT语句调用函数。

语法格式

Ø CALL [database_name.]proc_name([parameter_1[,…,parameter_n]]);

Ø SET @Variable_name = func_name([parameter_1[,…,parameter_n]]);

Ø SELECT @Variable_name;

 723 参数说明

参数名称

描  述

proc_name

要调用的存储过程名称。

parameter

调用参数。如果存储过程有参数,则必须按照存储过程的定义中的顺序和类型为参数赋值,同时,对于OUT和INOUT参数,必须指明OUT和INOUT关键字。

func_name

要调用的函数的名称。

Variable_name

变量名,可以将函数的执行结果赋予一个变量。

说明

l 针对无参数存储过程,<存储过程名称>后面是否添加括号,执行结果一致。

l GBase 8a MPP Cluster使用SELECT语句查看调用函数的执行结果。

示例

Ø 示例1:调用存储过程示例。

gbase> USE test;

Query OK, 0 rows affected

gbase> DELIMITER //

gbase> DROP PROCEDURE proc_count//

Query OK, 0 rows affected

gbase> CREATE PROCEDURE proc_count (OUT param1 INT,IN param2 varchar(10))

      BEGIN

      SELECT COUNT(*) INTO param1 FROM ssbm.customer WHERE c_nation= param2;

      END //

Query OK, 0 rows affected

gbase> CALL proc_count(@count1, 'JORDAN')//

Query OK, 0 rows affected

gbase> DELIMITER ;

gbase> SELECT @count1 ;

+---------+

| @count1 |

+---------+

|    1182 |

+---------+

1 row in set

Ø 示例2:调用函数示例。

gbase> USE test;

Query OK, 0 rows affected

gbase> DELIMITER //

gbase> DROP FUNCTION hello //

Query OK, 0 rows affected

gbase> CREATE FUNCTION hello (s CHAR(20)) RETURNS VARCHAR(50)

     RETURN CONCAT('Hello, ',s,'!') //

Query OK, 0 rows affected

gbase> DELIMITER ;

gbase> SET @result = hello('world');

Query OK, 0 rows affected

gbase> SELECT @result;

+------------------------------+

| @result                      |

+------------------------------+

| Hello, world               ! |

+------------------------------+

1 row in set

查看存储过程/函数的状态

查看存储过程/函数创建语句

功能说明

Ø 查看给定存储过程或函数的创建。

语法格式

SHOW CREATE {PROCEDURE | FUNCTION} ;

示例

Ø 示例1:显示创建存储过程proc_1的语句。

gbase> SHOW CREATE PROCEDURE vc1.demo.proc_1\G

*************************** 1. row ***************************

           Procedure: proc_1

            sql_mode: PIPES_AS_CONCAT,ANSI_QUOTES,IGNORE_SPACE,ONLY_FULL_GROUP_BY,NO_AUTO_VALUE_ON_ZERO,STRICT_ALL_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION,PAD_CHAR_TO_FULL_LENGTH

    Create Procedure: CREATE DEFINER="root"@"%" PROCEDURE "proc_1"()

begin

select 1;

end

character_set_client: utf8

collation_connection: utf8_general_ci

  Database Collation: utf8_general_ci

1 row in set (Elapsed: 00:00:00.00)

Ø 示例2:显示创建hello函数的语句。

gbase> show create function vc1.demo.hello\G

*************************** 1. row ***************************

            Function: hello

            sql_mode: PIPES_AS_CONCAT,ANSI_QUOTES,IGNORE_SPACE,ONLY_FULL_GROUP_BY,NO_AUTO_VALUE_ON_ZERO,STRICT_ALL_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION,PAD_CHAR_TO_FULL_LENGTH

     Create Function: CREATE DEFINER="root"@"%" FUNCTION "hello"(s CHAR(20)) RETURNS char(50) CHARSET utf8

RETURN CONCAT('Hello, ',s,'!')

character_set_client: utf8

collation_connection: utf8_general_ci

  Database Collation: utf8_general_ci

1 row in set (Elapsed: 00:00:00.00)

 查看存储过程或函数的状态

功能说明

Ø 查看创建或修改后的存储过程或函数的状态。

语法格式

SHOW {PROCEDURE | FUNCTION} STATUS;

示例

Ø 示例1:显示已经创建成功的函数的状态。

gbase> SHOW FUNCTION STATUS\G

*************************** 1. row ***************************

                  Vc: vc1

                  Db: demo                                                            

                Name: hello                                                           

                Type: FUNCTION

             Definer: root@%                                                                       

            Modified: 2020-07-15 19:26:08

             Created: 2020-07-15 19:26:08

       Security_type: DEFINER

             Comment:                                                                 

character_set_client: utf8                            

collation_connection: utf8_general_ci                 

  Database Collation: utf8_general_ci                 

1 row in set (Elapsed: 00:00:00.00)

Ø 示例2:显示vc1的demo库下已经创建成功的存储过程的状态。

gbase>  SHOW PROCEDURE STATUS where vc='vc1' and db='demo'\G

*************************** 1. row ***************************

                  Vc: vc1

                  Db: demo                                                            

                Name: proc_1                                                          

                Type: PROCEDURE

             Definer: root@%                                                                       

            Modified: 2020-07-15 19:25:14

             Created: 2020-07-15 19:25:14

       Security_type: DEFINER

             Comment:                                                                 

character_set_client: utf8                            

collation_connection: utf8_general_ci                 

  Database Collation: utf8_general_ci                 

1 row in set (Elapsed: 00:00:00.00)

你可能感兴趣的:(数据库,数据库,sql,database)