配色: 字号:
《MySQL 8.0数据库管理与应用》第6章 存储例程
2023-05-25 | 阅:  转:  |  分享 
  
第6章 存储例程6.1.1 创建存储过程使用CREATE PROCEDURE语句在数据库中创建存储过程:CREATE[DEFINER =
{用户 | CURRENT_USER }]PROCEDURE 存储过程名称([参数[, ...]])[特征 ...] 过程体参数
:[ IN | OUT | INOUT ] 参数名称 数据类型特征:COMMENT ''字符串''| LANGUAGE SQL| [N
OT] DETERMINISTIC| { CONTAINS SQL | NO SQL | READS SQL DATA | MOD
IFIES SQL DATA }| SQL SECURITY { DEFINER | INVOKER }6.1 存储过程6.1.
2 调用存储过程使用CALL语句调用存储过程:CALL 存储过程名称[()]CALL 存储过程名称([参数[, ...]])CA
LL语句调用先前使用CREATE PROCEDURE定义的存储过程。默认情况下,CALL语句将调用包含在当前数据库中的存储过程。如
果要调用包含在指定数据库中的存储过程,则应以“数据库名称.存储过程名称”格式来指定存储过程。1. 调用无参存储过程存储过程名称后面
的圆括号可以省略不写。2. 调用带IN参数的存储过程将常量、用户变量或其他表达式作为输入参数传入存储过程,然后在存储过程中使用所传
入的参数值。在CALL语句中使用的输入参数应与创建存储过程时定义的IN参数数量相同,数据类型一致。3. 调用带OUT参数和INOU
T参数的存储过程要使用OUT或INOUT参数从存储过程中获取值,可以通过用户变量向存储过程传递参数,并在存储过程返回后检查和使用用
户变量的值。6.1 存储过程6.1.2 调用存储过程4. 在预处理语句中调用存储过程使用预处理语句可以通过以下3个SQL语句来
实现。(1)使用PREPARE语句准备一个SQL语句并为其分配名称,以便稍后引用该语句:PREPARE stmt_name FRO
M preparable_stm;(2)使用EXECUTE语句执行先前通过PREPARE命名的语句:EXECUTE stmt_na
me [USING @var_name [, @var_name] ...];(3)使用DEALLOCATE PREPARE语句解
除先前用PREPARE生成的预处理语句,语法格式如下。{DEALLOCATE | DROP} PREPARE stmt_name在
与PREPARE和EXECUTE一起使用的预处理的CALL语句中,占位符可以用于IN参数、OUT参数和INOUT参数。6.1 存
储过程6.1.3 修改存储过程使用ALTER PROCEDURE语句对存储过程的特征进行修改:ALTER PROCEDURE 存
储过程名称 [特征 ...]特征:COMMENT ''字符串''| LANGUAGE SQL| { CONTAINS SQL | NO
SQL | READS SQL DATA | MODIFIES SQL DATA }| SQL SECURITY { DEFIN
ER | INVOKER }其中各个特征的作用与CREATE PROCEDURE语句相同。6.1 存储过程6.1.4 删除存储
过程使用DROP PROCEDURE语句从数据库中删除存储过程:DROP PROCEDURE [IF EXISTS] 存储过程名称
这个语句可以用于删除存储过程,即从服务器中删除指定的例程。要使用这个语句,必须拥有该过程的ALTER ROUTINE权限。如果启用
了automatic_sp_privileges系统变量,则在创建过程时会自动将该特权和EXECUTE权限授予过程的创建者,并在过
程被删除时从创建者中删除。IF EXISTS子句是MySQL扩展。如果存储过程不存在,使用该子句可以防止发生错误。6.1 存储过
程6.2.1 复合语句编写存储例程时可以使用BEGIN ... END复合语句来包含多个语句:[开始标签:] BEGIN[语句列
表]END [结束标签]其中语句列表可以包含一个或多个语句,每个语句都必须用分号“;”来结束。复合语句可以使用标签来标记。例如:l
able1: BEGIN USE test; SHOW TABLES; ...END label1使用多重语句需
要客户端能发送包含语句定界符“;”的查询字符串。这个符号在命令行客户端被用DELIMITER命令来处理,即对语句结束符“;”进行修
改,例如更改为“//”,这样就使得默认的语句结束符“;”可以用在子程序体中使用。除了BEGIN ... END之外,标签也可以用于
LOOP、REPEAT和WHILE语句。6.2 编写例程语句6.2.2 声明局部变量1. 使用DECLARE语句声明局部变量D
ECLARE 变量名[, ...] 类型 [DEFAULT 值]使用DECLARE语句声明局部变量时,需要指定变量的名称和数据类型
,还可以给变量提供一个默认值。与用户变量不同,命名局部变量时不要以@符号开头。DEFAULT子句用于给局部变量提供一个默认值,该默
认值可以指定为一个表达式。如果没有DEFAULT子句,则变量的初始值为NULL。2. 使用SET语句设置局部变量SET 变量=表达
式[, 变量=表达式] ...其中变量可以是子程序内声明的局部变量,也可以是用户变量或系统变量。在存储例程中使用的SET语句是一般
SET语句的扩展版本,允许使用SET a=x, b=y, ...这样的扩展语法。3. 使用SELECT ... INTO语句将列值
存储到局部变量中SELECT 列名[, ...] INTO 变量名[, ...] FROM 表名6.2 编写例程语句6.2.2
声明局部变量1. 使用DECLARE语句声明局部变量DECLARE 变量名[, ...] 类型 [DEFAULT 值]使用DEC
LARE语句声明局部变量时,需要指定变量的名称和数据类型,还可以给变量提供一个默认值。与用户变量不同,命名局部变量时不要以@符号开
头。DEFAULT子句用于给局部变量提供一个默认值,该默认值可以指定为一个表达式。如果没有DEFAULT子句,则变量的初始值为NU
LL。2. 使用SET语句设置局部变量SET 变量=表达式[, 变量=表达式] ...其中变量可以是子程序内声明的局部变量,也可以
是用户变量或系统变量。在存储例程中使用的SET语句是一般SET语句的扩展版本,允许使用SET a=x, b=y, ...这样的扩展
语法。3. 使用SELECT ... INTO语句将列值存储到局部变量中SELECT 列名[, ...] INTO 变量名[, .
..] FROM 表名6.2 编写例程语句6.2.3 条件语句1. IF语句在存储例程中使用IF语句实现来一个基本的选择结构:
IF 条件 THEN 语句序列[ELSEIF 条件 THEN 语句序列] ...[ELSE 语句序列]END I
FIF语句的执行流程是:首先对IF后面的条件表达式进行计算,如果计算结果为真,则执行THEN后面的语句序列;否则计算ELSEIF后
面的条件,如果计算结果为真,则执行相应的THEN后面的语句序列,以此类推。如果所有条件都不为真,则执行ELSE子句中的语句序列。语
句序列可以包含一个或多个语句,不允许使用空的语句序列。6.2 编写例程语句6.2.3 条件语句2. CASE语句(1)将一个输
入表达式的值与一组匹配表达式的值进行比较以确定要执行的语句序列:CASE 输入表达式 WHEN 匹配表达式 THEN
语句序列 [WHEN 匹配表达式 THEN 语句序列] ... [ELSE
语句序列]END CASE执行这种格式的CASE语句时,首先计算CASE后面的输入表达式的值,然后将该值与第一个WHEN关键字后
面的匹配表达式进行比较,如果两者相等,则执行第一个THEN后面的语句序列;否则与第二个WHEN匹配表达式进行比较,如果两者相等,则
执行相应的THEN后面的语句序列,以引类推。如果WHEN输入表达式的值与任何WHEN匹配表达式的值都不相等,则执行ELSE关键字后
面的语句序列。6.2 编写例程语句6.2.3 条件语句2. CASE语句(2)计算一组表达式的值以确定要执行的语句序列,语法格
式如下。CASE WHEN 条件THEN 语句序列 [WHEN 条件THEN 语句序列]
...[ELSE 语句序列]END CASE执行这种格式的CASE语句时,首先计算第一个WHEN关键字后面的条件的值
,如果该值为TRUE,则执行第一个THEN后面的语句序列;否则计算第二个WHEN条件的值,如果该值为TRUE,则执行相应的THEN
后面的语句序列,以此类推。如果所有条件均为FALSE,则执行ELSE后面的语句序列。6.2 编写例程语句6.2.4 循环语句1
. WHILE语句WHILE语句的功能在循环条件为真时重复执行一组语句:[开始标签:] WHILE 条件 DO 语句序列EN
D WHILE [结束标签]WHILE语句的执行流程如下:首先计算WHILE关键字后面的循环条件的值,如果该值为真,则执行一次DO
关键字后面的语句序列(循环体);然后再次计算循环条件的值,如果该值仍为真,则继续执行循环体,以此类推;直至循环条件变为假,结束循环
。WHILE语句可以使用标签进行标注。除非存在开始标签,才能使用结束标签。如果两者都存在,则它们必须是相同的。6.2 编写例程语
句6.2.4 循环语句2. REPEAT语句REPEAT语句的功能是当给定条件为假时重复执行一组语句,语法格式如下。[开始标签:
] REPEAT 语句序列UNTIL 条件END REPEAT [结束标签]REPEAT语句的执行流程如下:首先执行一次循环
体内的语句序列(循环体),然后计算UNTIL关键字后面的条件表达式的值,如果该值为假,则继续执行循环体,以此类推;直至条件表达式变
为真,结束循环。REPEAT语句可以使用标签进行标注。除非存在开始标签,结束标签才能使用。如果两者都存在,则它们必须是一样的。6.
2 编写例程语句6.2.4 循环语句3. LOOP语句LOOP语句用于无条件重复执行一组语句,语法格式如下。[开始标签:] L
OOP 语句序列END LOOP [结束标签]LOOP语句用于实现一个简单的循环结构,可以一直重复执行循环体内的语句,直至退
出循环。LOOP语句可以使用标签进行标注。LOOP语句本身并不能进行条件判断。要退出循环,通常需要在循环体内使用一个IF语句,当给
出条件为真时执行一个LEAVE语句,从而结束循环体的执行。LEAVE语句用于退出任何被标注的流程控制结构,它与BEGIN ...
END或循环一起被使用,语法格式如下。LEAVE 标签在循环语句中,还可以与IF语句一起使用ITERATE语句,当给出条件为真时提
前结束本轮循环,继续执行下一轮循环,语法格式如下。ITERATE 标签6.2 编写例程语句6.2.5 错误处理程序1. 命名条
件DECLARE 条件名称 CONDITION FOR 条件值条件值:MySQL错误代码 | SQLSTATE [VALUE] S
QLSTATE值2. 声明处理程序DECLARE 处理程序操作 HANDLER FOR 条件值[, 条件值] ...处理语句处理程
序操作:CONTINUE | EXIT | UNDO条件值:MySQL错误代码 | SQLSTATE [VALUE] SQL状态值
|条件名称 | SQLWARNING | NOT FOUND | SQLEXCEPTION6.2 编写例程语句6.2.5 错误
处理程序声明处理程序的常见格式:(1)基于MySQL错误代码命名一个条件并在声明处理程序时引用该名称(2)基于SQLSTATE值命
名一个错误条件并在声明处理程序时引用该名称(3)基于SQLWARNING条件声明处理程序(4)基于NOT FOUND条件声明处理程
序(5)基于SQLEXCEPTION条件声明处理程序6.2 编写例程语句6.2.6 游标1. 声明游标DECLARE 游标名称
CURSOR FOR SELECT语句2. 打开游标OPEN 游标名称3. 使用游标FETCH [[NEXT] FROM] 游标
名称 INTO 变量名[, 变量名] ...4. 关闭游标CLOSE 游标名称6.2 编写例程语句6.3.1 创建存储函数使用
CREATE FUNCTION语句在数据库中创建存储函数:CREATE[DEFINER = {用户 | CURRENT_USER
}]FUNCTION 存储函数名称([参数[, ...]])RETURNS 类型[特征 ...] 函数体参数:参数名 类型类型:任
何有效的MySQL数据类型特征:COMMENT ''字符串''| LANGUAGE SQL| [NOT] DETERMINISTIC|
{ CONTAINS SQL | NO SQL | READS SQL DATA | MODIFIES SQL DATA }|
SQL SECURITY { DEFINER | INVOKER }函数体:有效的SQL例程语句6.3 存储函数6.3.2 调
用存储函数在数据库中创建存储函数之后,可以像调用MySQL系统内置函数一样在表达式中引用该函数:存储函数名称([参数[, ...]
])在表达式求值过程中存储函数会返回一个值。不能使用CALL语句来调用存储函数。6.3.3 修改存储函数使用ALTER FUNC
TION语句修改现有存储函数的特征:ALTER FUNCTION 存储函数名称 [特征 ...]特征:COMMENT ''字符串''|
LANGUAGE SQL| { CONTAINS SQL | NO SQL | READS SQL DATA | MODIFIE
S SQL DATA }| SQL SECURITY { DEFINER | INVOKER }6.3 存储函数6.3.4 删
除存储函数对于不再需要的存储函数,可以使用DROP FUNCTION语句将其删除,语法格式如下。DROP FUNCTION [IF
EXISTS] 存储函数名称其中存储函数名称指定要删除的存储函数。IF EXISTS子句是MySQL扩展。如果存储函数不存在,使
用该子句可以防止发生错误。要使用DROP FUNCTION语句,必须拥有该函数的ALTER ROUTINE权限。例如,下面的语句从
test数据库中删除名为sf的存储函数。USE test;DROP FUNCTION sf;6.3 存储函数6.4.1 创建触
发器使用CREATE TRIGGER创建一个新的触发器:CREATE[DEFINER = {用户 | CURRENT_USER}]
TRIGGER 触发器名称 触发时间 触发事件ON 表名称 FOR EACH ROW[触发顺序] 触发器主体触发时间:{ BEFO
RE | AFTER }触发事件:{ INSERT | UPDATE | DELETE }触发顺序:{ FOLLOWS | PRE
CEDES } 其他触发器名称6.4 触发器6.4.2 删除触发器对于不再需要的触发器,可以使用DROP TRIGGER语句将
其删除,语法格式如下。DROP TRIGGER [IF EXISTS] [数据库名称.]触发器名称执行DROP TRIGGER语句
需要拥有与触发器关联的表的TRIGGER权限。默认情况下,该语句用于从当前数据库中删除给定的触发器。如果要从指定的数据库中删除触发
器,则应使用可选的数据库名称。如果省略数据库名称,则会从当前数据库中删除触发器。使用IF EXISTS子句,可以防止删除不存在的触
发器发生错误。例如,下面的语句用于删除名tr1的触发器。mysql> USE test;mysql> DROP TRIGGER I
F EXISTS tr1;6.4 触发器6.5.1 创建事件使用CREATE EVENT语句创建并计划一个新事件:CREATE
[DEFINER={用户 | CURRENT_USER}]EVENT [IF NOT EXISTS]事件名称 ON SCHEDU
LE 事件调度[ON COMPLETION [NOT] PRESERVE][ENABLE | DISABLE | DISABLE
ON SLAVE][COMMENT ''字符串’] DO 事件主体;事件调度:AT 时间戳 [+ INTERVAL间隔] ...|E
VERY 间隔[STARTS 时间戳 [+ INTERVAL 间隔] ...][ENDS 时间戳 [+ INTERVAL 间隔]
...]间隔:数量 {YEAR | QUARTER | MONTH | DAY | HOUR | MINUTE | WEEK |
SECOND | YEAR_MONTH | DAY_HOUR | DAY_MINUTE | DAY_SECOND | HOUR_MINUTE | HOUR_SECOND | MINUTE_SECOND}6.5 事件6.5.2 修改事件使用ALTER EVENT语句可以对现有事件进行修改:ALTER[DEFINER={用户 | CURRENT_USER}]EVENT 事件名称[ON SCHEDULE 事件调度][ON COMPLETION [NOT] PRESERVE][RENAME TO 新事件名称][ENABLE | DISABLE | DISABLE ON SLAVE][COMMENT ''字符串''][DO 事件主体]6.5 事件6.5.3 删除事件对于不再需要的事件,可以使用DROP EVENT语句将其删除,语法格式如下。DROP EVENT [IF EXISTS] 事件名称执行DROP EVENT语句需要拥有待删除事件所属数据库的EVENT权限。此语句用于删除具有给定名称的事件。该事件立即停止活动,并从服务器中完全删除。如果指定的事件不存在,则会出现错误。使用IF EXISTS会覆盖错误并为不存在的事件生成警告。6.5 事件
献花(0)
+1
(本文系大高老师首藏)