存储过程是一组可以完成特定功能的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 Ø [characteristic ...] routine_body |
Ø CREATE FUNCTION Ø 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: Ø { 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) |