MySQL中Procedure事务编写基础笔记

时间:2022-02-07 02:08:05

原文:MySQL中Procedure事务编写基础笔记

目录:

一、PROCEDURE;

二、CREATE PROCEDURE基本语法;

三、PROCEDURE小进阶

  3.1、基本的DECLARE语句;

  3.2、声明HANDLER句柄;

  3.3、声明CURSOR游标;

  3.4、循环语句;

四、顺带提一下触发器TRIGGER

一、PROCEDURE:

PROCEDURE,事务,一个存储过程,实际上就是在服务器端直接在数据库中编写一段代码作运算,在服务器端进行高效的运算,运算结果直接返还给客户端。

它和FUNCTION一个明显的不同点是,FUNCTION最后会有RETURN语句,返回运算结果,PROCEDURE不允许有RETURN语句的,但是可以在参数表中指定返还数据。

PROCEDURE编译完成后会存储在数据库中,需要调用的时候使用CALL语句对事务或者函数进行调用。编写PROCEDURE不仅可以避免重复编码,同时还可以提高计算效率。

二、CREATE PROCEDURE基本语法:

下面不妨先看一看CREATE PROCEDURE以及CREATE FUNCTION的语法:

 CREATE
[DEFINER = { user | CURRENT_USER }]
PROCEDURE sp_name ([proc_parameter[,...]])
[characteristic ...] routine_body
CREATE
[DEFINER = { user | CURRENT_USER }]
FUNCTION sp_name ([func_parameter[,...]])
RETURNS type
[characteristic ...] routine_body
proc_parameter:
[ IN | OUT | INOUT ] param_name type
func_parameter:
param_name type
type:
Any valid MySQL data type
characteristic:
COMMENT 'string'
| LANGUAGE SQL
| [NOT] DETERMINISTIC
| { CONTAINS SQL | NO SQL | READS SQL DATA | MODIFIES SQL DATA }
| SQL SECURITY { DEFINER | INVOKER }
routine_body:
Valid SQL routine statement

其中有几个注意点是:

1,DEFINER你可以用这个选项指定可以调用该PROCEDURE的用户,比如说允许本地的用户nero使用,那么可以指定为:DEFINER='nero'@'localhost',如果这个事务就是创建给当前用户使用的,那么可以指定为:DEFINER=CURRENT_USER。

2,事务安全性:characteristic中如果使用了SQL SECURITY,那么事务每次执行的时候,指定的安全上下文都会被执行,它们会检查当前执行这个事务的人是否拥有执行权限。

比如说下面这个小例子:

delimiter //         --指定临时分隔符
CREATE DEFINER = 'nero'@'localhost' PROCEDURE simpleTest(OUT outParam int, IN inParam int) SQL SECURITY INVOKE
BEGIN
SELECT COUNT(*) INTO outParam FROM tbl WHERE col < inParam;
END;
delimter ;

像上面这个例子,我们在定义的时候启用了“SQL SECURITY INVOKE”,只有是:a,对这个事务有调用权限;b,对这个表tbl有select权限的用户才能成功执行该PROCEDURE

而在形参部分,则是通过OUTIN指明参数传入还是传出,如果某个参数在传入之后要作为结果传出,那么不需要作特定指示,直接写明参数名称和参数类型即可。

调用这个事务则用CALL表达式即可:

SET @b=100;
CALL simpleTest(@a,@b);
SELECT @a; --显示结果

三、PROCEDURE小进阶:

知道PROCEDURE的基本语法以后,学习一下编写一个PROCEDURE经常需要用到的语句,分别有:DECLARE声明语句,SET设值语句,DECLARE...HANDLER句柄声明语句,DECLARE...CURSOR游标声明语句;条件判断IFCASE;三种循环体:LOOP,REPEAT,WHILE

3.1、基本的DECLARE语句:

DECLARE基本语法:

DECLARE var_name [, var_name] ... type [DEFAULT value]

比如说在某个事务中声明几个临时变量:

CREATE PROCEDURE test()
BEGIN
DECLARE usrID INT ;
DECLARE usrName VARCHAR(10) DEFAULT 'NERO';
.......... --一些事务操作
END;

3.2、声明HANDLER句柄:

基本语法:

 DECLARE handler_type HANDLER
FOR condition_value [, condition_value] ...
statement
handler_type:
CONTINUE
| EXIT
| UNDO
condition_value:
SQLSTATE [VALUE] sqlstate_value
| condition_name
| SQLWARNING
| NOT FOUND
| SQLEXCEPTION
| mysql_error_code

句柄的作用,就是在condition_value中,如果指定的任意条件出现了,那么statement这里的指定语句就会被执行。conditions条件有几种类型:

1、SQLSTATE指的是当前SQL返回的状态,这个对应的状态就比较多了,比如状态Error: 1169 SQLSTATE: 23000,指的是”因特定限制而导致的无法写入的错误“;Error: 1162 SQLSTATE: 42000 ,指的是”结果字符串超过了最大限制“。相关的状态代码请自行查阅帮助文档的”Server Error Codes and Messages“词条。

2、SQLWARNING,但凡是SQL发出的警告信息。

3、NOT FOUND,一般来说出现在SELECT语句中,游标触底;

4、SQLEXCEPTION,SQL错误。

不同的结果分别对应:

1、CONTINUE,如果条件成立,那么,在执行句柄的statement之后再继续执行程序,比如说下面这个例子:

 CREATE TABLE tbl(col INT ,PRIMARY KEY(col));

 delimiter //

 CREATE PROCEDURE HANDLER_DEMO()
BEGIN
DECLARE CONTINUE HANDLER FOR SQLSTATE '' SET @x2 = 1;
SET @x = 1;
INSERT INTO tbl VALUES(1);
SET @x = 2;
INSERT INTO tbl VALUES(1); --触发句柄的statement执行
SET @x = 3;
END;
// CALLL HANDLER_DEMO()// SELECT @x //
SELECT @x2 // delimiter ;

结果当然是@x为3,@x2为1了。在代码11行,重复插入相同的值到主键上触发了23000错误,因而执行statement:SET @x2 = 1,然后再继续执行主程序的SET @x = 3.

2、EXIT,一旦条件被触发,当前BEGIN...END闭合语句将会终止执行,比如说:

 delimiter //
CREATE PROCEDURE EXIT_DEMO()
BEGIN
BEGIN
DECLARE EXIT HANDLER FOR SQLSTATE ''
.......
END;
END;
delimiter ;

上述代码中,一旦出现23000错误,代码行4到7的BEGIN...END闭合语句立刻终止执行。

3.3、声明CURSOR游标 :

声明一个CURSOR游标:

DECLARE cursor_name CURSOR FOR select_statement

比如说最基本的:

DECLARE cur1 CURSOR FOR SELECT id,data FROM tbl;

此时cur1表示的即是SELECT语句返回的首个结果,有点类似于指针。

下面不妨看一个比较完整的例子:

 delimiter //
CREATE PROCEDURE CURSOR_DEMO()
BEGIN
DECLARE done INT DEFAULT 0; --INT型值,默认为0
DECLARE a CHAR(5);
DECLARE b,c INT;
/*声明两个游标*/
DECLARE CUR1 CURSOR FOR SELECT ID,DATA FROM tbl1;
DECLARE CUR2 CURSOR FOR SELECT I FROM tbl2;
/*声明CONTINUE句柄,当游标触底时被触发*/
DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = 1; /*打开游标*/
OPEN CUR1;
OPEN CUR2; /*循环插入数据,使用REPEAT...UNTIL语句*/
REPEAT
FETCH CUR1 INTO a,b; --读取游标中的数据,并移向下一行
FETCH CUR2 INTO c;
IF NOT done THEN --当done为0的时候条件成立
IF b < c THEN --取b和c的较小者插入表3
INSERT INTO tbl3 VALUES(a,b);
ELSE
INSERT INTO tbl3 VALUES(a,c);
END IF;
END IF; --当游标触底,句柄将被触发,done值被设为1,然后从这里继续执行主程序
UNTIL done --句柄触发后,done为1,执行UNTIL
END REPEAT; /*使用完毕,关闭游标*/
CLOSE CUR1;
CLOSE CUR2;
END// delimiter ;

其中,FETCH语句的基本语法如下:

FETCH cursor_name INTO var_name [, var_name] ...

该语句每次都会返回SELECT结果中的下一行(如果有的话)。

3.4、循环语句:

循环涉及到的语句有:1、LOOP、ITERATE和LEAVE;2、REPEAT;3、WHILE

下面直接给出对应的循环例子:

1、LOOP、ITERATE和LEAVE:

/*LOOP,ITERATE,LEAVE*/
delimiter // CREATE PROCEDURE LOOP_DEMO(param INT)
BEGIN
label1: LOOP
SET param = param +1;
IF param < 100 THEN
ITERATE label1; --回到标签开始处
END IF;
LEAVE label1; --离开标签,退出流控制结构
END LOOP label1; --结束循环
END; delimiter ;

2、REPEAT:

先给出REPEAT语法定义:

 [begin_label:] REPEAT
statement_list
UNTIL search_condition
END REPEAT [end_label]

可见,同样是可以在代码开始处插入label标签,不过REPEAT循环是自己有控制条件的,最好能直接使用UNTIL来进行条件判断。

比如下面这个例子:

 delimiter //
CREATE PROCEDURE REPEAT_DEMO(param INT)
BEGIN
SET @x = 0;
REPEAT
SET @x = @x+1;
UNTIL @x > param
END REPEAT;
END// delimiter ;

3、WHILE:

WHILE循环语法定义如下:

[begin_label:] WHILE search_condition DO
statement_list
END WHILE [end_label]

比如下面这个小例子:

delimiter //

CREATE PROCEDURE WHILE_DEMO()
BEGIN
SET param INT DEFAULT 10;
WHILE param < 1000
.... --循环内书写具体需要处理的事务
SET param = param + 100;
END WHILE;
END; delimiter ;

四、顺带提一下触发器TRIGGER:

触发器都是和某个特定的表相关联的,对该表设定触发器以后,一旦对这个表进行了某个特定操作(诸如INSERT,UPDATE,DELETE),触发器就会被触发。

先给出CREATE TRIGGER语法定义:

CREATE
[DEFINER = { user | CURRENT_USER }]
TRIGGER trigger_name trigger_time trigger_event
ON tbl_name FOR EACH ROW trigger_body

同样的,可以通过DEFINER自行指定触发器的适用对象。

在trigger_time中可以指定触发时间(诸如:BEFORE,AFTER),trigger_event前面已经提到过了,另外,DROP TABLE或TRUNCATE TABLE这种操作是不会触发TRIGGER的。

下面给出个小例子:

 delimiter //
CREATE DEFINER 'nero'@'localhost' TRIGGER trigger_demo
BEFORE INSERT ON tbl1 FOR EACH ROW
BEGIN
INSERT INTO tbl2 VALUES(...........); --INSERT操作
DELETE FROM tbl3 WHERE .......... ; --删除操作
UPDATE tbl4 SET col1 = ...... ; --更新操作
END; //
delimiter ;

这样,一旦本地用户nero对表tbl1进行INSERT操作的时候(之前,这里设置的是BEFORE),BEGIN...END内的内容就会被执行。

MySQL中Procedure事务编写基础笔记的更多相关文章

  1. 举例说明MySQL中的事务

    一.场景导入 现在有一张仓库表,仓库表中记录了每一个物品的数量,还有一张用户表,用户购买产品,仓库表的产品数量减少,而用户拥有产品的数量增加. 但是如果仓库中的产品数量不足时怎么处理? 例子: #仓库 ...

  2. 【转】全面了解Mysql中的事务

    为什么要有事务? 事务广泛的运用于订单系统.银行系统等多种场景.如果有以下一个场景:A用户和B用户是银行的储户.现在A要给B转账500元.那么需要做以下几件事: 1. 检查A的账户余额>500元 ...

  3. 【MySQL】漫谈MySQL中的事务及其实现

    最近一直在做订单类的项目,使用了事务.我们的数据库选用的是MySQL,存储引擎选用innoDB,innoDB对事务有着良好的支持.这篇文章我们一起来扒一扒事务相关的知识. 为什么要有事务? 事务广泛的 ...

  4. 漫谈MySql中的事务

    最近一直在做订单类的项目,使用了事务.我们的数据库选用的是MySql,存储引擎选用innoDB,innoDB对事务有着良好的支持.这篇文章我们一起来扒一扒事务相关的知识. 为什么要有事务? 事务广泛的 ...

  5. MySql中的事务嵌套

    1.Mysql中的事务必须是InnoDB.Berkeley DB引擎,myisam不支持. 2.Mysql是不支持嵌套事务的,开启了一个事务的情况下,再开启一个事务,会隐式的提交上一个事务. 3.My ...

  6. MySql中的事务、JDBC事务、事务隔离级别

    一.MySql事务 之前在Oracle中已经学习过事务了,这个东西就是这个东西,但是在MySql中用法还是有一点不同,正好再次回顾一下. 先看看MySql中的事务,默认情况下,每执行一条SQL语句,都 ...

  7. &lpar;转&rpar;漫谈MySql中的事务

    最近一直在做订单类的项目,使用了事务.我们的数据库选用的是MySql,存储引擎选用innoDB,innoDB对事务有着良好的支持.这篇文章我们一起来扒一扒事务相关的知识. 为什么要有事务? 事务广泛的 ...

  8. 在MySQL中设置事务隔离级别有2种方法&colon;

    在MySQL中设置事务隔离级别有2种方法: 1 在my.cnf中设置,在mysqld选项中如下设置 [mysqld] transaction-isolation = READ-COMMITTED 2 ...

  9. 十:MYSQL中的事务

    前言: 因为没有多少时间和精力,目前无法深入研究数据库中的事务,比如 但是,对于事务的一些基本知识,还是需要牢牢掌握的,做到了解事务的基本常识,在实际开发中能够理解各个持久层框架对事务的处理 一:是么 ...

随机推荐

  1. 使用功能强大的插件FastReport&period;Net打印报表实例

    我第一次使用FastReport插件做的功能是打印一个十分复杂的excel表格,有几百个字段都需要绑定数据,至少需要4个数据源,而且用到横向.竖向合并单元格. 我不是直接连接数据库,而是使用Regis ...

  2. 《JavaScript高级程序设计》读书笔记--(2)基本概念

    变量 Javascript 是区分大小写的, 也就是说 var nun 与 var Num 是不同的变量. ECMAScript的变量是松散类型的,所谓松散类型就是可以保存任何类型的数据.ECMASc ...

  3. ulimit 命令

    用途:ulimit用于shell启动进程所占用的资源. 类别:shell内建命令 语法格式:ulimit [-acdfHlmnpsStvw] [size] 参数: -H 设置硬资源限制. -S 设置软 ...

  4. eclipse 安装git插件

    Eclipse上安装GIT插件EGit及使用 博客分类: GIT   一.Eclipse上安装GIT插件EGit Eclipse的版本eclipse-java-helios-SR2-win32.zip ...

  5. hdu&lowbar;5761&lowbar;Rower Bo&lpar;xjb猜公式&rpar;

    题目链接:hdu_5761_Rower Bo 题意: 让你求一个物理问题 题解: xjb猜公式,由题目样例可得,答案为8/7,然后我们可以xjb猜出公式为v1*a/(v1*v1-v2*v2),然后特判 ...

  6. LeetCode OJ 108&period; Convert Sorted Array to Binary Search Tree

    Given an array where elements are sorted in ascending order, convert it to a height balanced BST. 把一 ...

  7. FeathersJS简单使用指南,一个前端也能玩得转的后端框架

    官方文档 :https://docs.feathersjs.com/api/services.html#createdata-params 第一步,创建接口和服务 app.use("user ...

  8. &lbrack;再寄小读者之数学篇&rsqb;&lpar;2014-06-22 发散级数 &lbrack;中国科学技术大学2012年高等数学B考研试题&rsqb;&rpar;

    设 $a_n>0$, $S_n=a_1+a_2+\cdots+a_n$, 级数 $\dps{\vsm{n}a_n}$ 发散, 证明: $\dps{\vsm{n}\cfrac{a_n}{S_n}} ...

  9. P1169 &lbrack;ZJOI2007&rsqb;棋盘制作 DP悬线法

    题目描述 国际象棋是世界上最古老的博弈游戏之一,和中国的围棋.象棋以及日本的将棋同享盛名.据说国际象棋起源于易经的思想,棋盘是一个8 \times 88×8大小的黑白相间的方阵,对应八八六十四卦,黑白 ...

  10. web框架实现购物车数量加减

    企业开发中经常是团队协作,每个人分配一个小的模块,比如说购物车模块,数量加减这一块人们首先想到的就是通过jquery实现,其实作为一个后端接口开发的程序猿也可以用自己更擅长的后端的逻辑代码来实现,那我 ...