Mysql 存储过程的学习笔记

技术要点

一个存储过程包括名字、参数列表,以及可以包括很多SQL语句的SQL语句集。下面为一个存储过程的定义过程:
create procedure proc_name (in parameter integer)begindeclare variable varchar(20);if parameter=1 thenset variable='MySQL';elseset variable='PHP';end if;insert into tb (name) values (variable);end;

MySQL中存储过程的建立以关键字create procedure开始,后面紧跟存储过程的名称和参数。MySQL的存储过程名称不区分大小写,例如PROCE1()和proce1()代表同一个存储过程名。存储过程名不能与MySQL数据库中的内建函数重名。
存储过程的参数一般由3部分组成。第一部分可以是in、out或inout。in表示向存储过程中传入参数;out表示向外传出参数;inout表示定义的参数可传入存储过程,并可以被存储过程修改后传出存储过程,存储过程默认为传入参数,所以参数in可以省略。第二部分为参数名。第三部分为参数的类型,该类型为MySQL数据库中所有可用的字段类型,如果有多个参数,参数之间可以用逗号进行分割。
MySQL存储过程的语句块以begin开始,以end结束。语句体中可以包含变量的声明、控制语句、SQL查询语句等。由于存储过程内部语句要以分号结束,所以在定义存储过程前应将语句结束标志“;”更改为其他字符,并且该字符在存储过程中出现的几率也应该较低,可以用关键字delimiter更改。例如:
mysql>delimiter //

存储过程创建之后,可用如下语句进行删除,参数proc_name指存储过程名。
drop procedure proc_name

实现过程

(1)MySQL存储过程是在“命令提示符”下创建的,所以首先应该打开“命令提示符”窗口。
(2)进入“命令提示符”窗口后,首先应该登录MySQL数据库服务器,在“命令提示符”下输入如下命令:
mysql –u用户名 –p用户密码

(3)更改语句结束符号,本实例将语句结束符更改为“//”。代码如下:
delimiter //

(4)创建存储过程前应首先选择某个数据库。代码如下:
use 数据库名

(5)创建存储过程。
(6)通过call语句调用存储过程。

举一反三

-- 建表

use test;
create table user(
id mediumint(8) unsigned not null auto_increment,
name char(15) not null default '',
pass char(32) not null default '',
note text not null,
primary key (id)
)engine=Innodb charset=utf8;

-- 示例一

delimiter //
create procedure proc_name (in parameter integer)
begin
if parameter=0 then
select * from user order by id asc;
else
select * from user order by id desc;
end if;
end;
//
delimiter ;
show warnings;
call proc_name(1);
call proc_name(0);

-- 示例二

drop procedure proc_name;
delimiter //
create procedure proc_name (in parameter integer)
begin
declare variable varchar(20);
if parameter=1 then
set variable='Windows';
else
set variable='Linux';
end if;
select parameter;
end;
//
delimiter ;
show warnings;
call proc_name(1);
call proc_name(0);

存储过程中使用事务transaction

一.在处理事务时,使用SQLException捕获SQL错误,然后处理; 按照这个推论,我们必须在MySQL存储过程中捕获SQL错误,最后判断是回滚(ROLLBACK)还是提交(COMMIT)。 所以存储过程为:

DELIMITER $$ 
DROP PROCEDURE IF EXISTS  test_sp1 $$ 
CREATE PROCEDURE test_sp1( ) 
    BEGIN 
    DECLARE t_error INTEGER DEFAULT 0; 
    DECLARE CONTINUE HANDLER FOR SQLEXCEPTION SET t_error=1; 
 
        START TRANSACTION; 
            INSERT INTO test VALUES(NULL, 'test sql 001');    
            INSERT INTO test VALUES('1', 'test sql 002');    
 
        IF t_error = 1 THEN 
            ROLLBACK; 
        ELSE 
            COMMIT; 
        END IF; 
 
    END$$ 
DELIMITER ; 

在这个例子中,我们为test_sp1() 定义了一个 SQLEXCEPTION 参数 t_error, 在遇到SQL错误时,继续执行(CONTINUE); 如果执行状态没有错误,则提交,反之回滚!

二.在调用事务时,将事务的执行状态(即:事务是提交了还是回滚了),返回给被调者。

下面给出另一个例子:

CREATE DEFINER=`3dmodelbaseadmin`@`%` PROCEDURE `p_userConfirmPay`(
in p_lID int,
in p_endTime DATETIME,
in p_moneyAfterTax decimal(10,2),
in p_integralAfterTax decimal(10,0),
in p_sellerID int unsigned,
in p_cashOrPoints int,
in p_loginName_site varchar(50),
in p_transactionID_site char(100),
in p_orderID char(100),
in p_remarks_site char(100),
in p_transactionID char(100),
in p_cMEMID INT UNSIGNED,
in p_curTotal DECIMAL(10,2),
in p_curTotalcIntegral decimal(10,0),
in p_remarks char(100))
BEGIN

DECLARE p_cMEMID_site INT;
DECLARE p_balance_site DECIMAL(10,2);
DECLARE p_balance DECIMAL(10,2);
DECLARE p_intBalance_site DECIMAL(10,0);
DECLARE p_intBalance DECIMAL(10,0);

DECLARE t_error INTEGER DEFAULT 0;
DECLARE CONTINUE HANDLER FOR SQLEXCEPTION SET t_error=1;

START TRANSACTION;

set p_cMEMID_site=(select cMEMID from m_member where cLoginName=p_loginName_site);

update l_memberdownlog set lState=1,endTime=p_endTime where lID=p_lID;

update m_memberMoney set cMoney=cMoney-p_moneyAfterTax,
cIntegral = cIntegral-p_integralAfterTax where cMEMID=p_cMEMID_site;

update m_memberMoney set cMoney=cMoney+p_moneyAfterTax,
cIntegral = cIntegral+p_integralAfterTax where cMEMID=p_sellerID;

if p_cashOrPoints=0 then
  set p_balance_site = (select cMoney from m_memberMoney where cMEMID=p_cMEMID_site);
  INSERT INTO cashDetail ......(此处省略);
else
  set p_intBalance_site = (select cIntegral from m_memberMoney where cMEMID=p_cMEMID_site);
  INSERT INTO integralDetail ......(此处省略);
end if;

update m_memberMoney set totalConsMoney=totalConsMoney+p_curTotal,
totalConsIntegral=totalConsIntegral+p_curTotalcIntegral where cMEMID=p_cMEMID;

IF t_error = 1 THEN
    ROLLBACK;
ELSE
    COMMIT;
END IF;

select t_error;  将事务的执行状态返回给被调者

MySql存储过程游标(Cursor)

1、游标的作用及属性

游标的作用就是用于对查询数据库所返回的记录进行遍历,以便进行相应的操作;游标有下面这些属性:

    a、游标是只读的,也就是不能更新它;

    b、游标是不能滚动的,也就是只能在一个方向上进行遍历,不能在记录之间随意进退,不能跳过某些记录;

    c、避免在已经打开游标的表上更新数据。

2、如何使用游标

使用游标需要遵循下面步骤:

a、首先用DECLARE语句声明一个游标             

DECLARE cursor_name CURSOR FOR SELECT_statement; 
上面这条语句就对,我们执行的select语句返回的记录指定了一个游标  
     b、其次需要使用OPEN语句来打开上面你定义的游标

OPEN cursor_name; 
     c、接下来你可以用FETCH语句来获得下一行数据,并且游标也将移动到对应的记录上(这个就类似java里面的那个iterator)。

FETCH cursor_name INTO variable list; 
     d、然后最后当我们所需要进行的操作都结束后我们要把游标释放掉。

CLOSE cursor_name; 
在使用游标时需要注意的是,使用定义一个针对NOT FOUND的条件处理函数(condition handler)来避免出现“no data to fetch”这样的错误,条件处理函数就是当某种条件产生时所执行的代码,这里但我们游标指到记录的末尾时,便达到NOT FOUND这样条件,这个时候我们希望继续进行后面的操作,所以我们会在下面的代码中看到一个CONTINUE。先看看我们的表格内容:

下面的游标使用演示获取库存量小于100的产品的代码code,这个代码纯粹演示如何使用,在这里没有其他任何意义:)

DELIMITER $$ 
 
DROP PROCEDURE IF EXISTS `test`.`CursorProc` $$ 
CREATE PROCEDURE `test`.`CursorProc` () 
BEGIN 
 DECLARE  no_more_products, quantity_in_stock INT DEFAULT 0; 
 DECLARE  prd_code VARCHAR(255); 
 DECLARE  cur_product CURSOR FOR   SELECT code FROM products;  /*First: Delcare a cursor,首先这里对游标进行定义*/ 
 DECLARE  CONTINUE HANDLER FOR NOT FOUND  SET  no_more_products = 1; /*when "not found" occur,just continue,这个是个条件处理,针对NOT FOUND的条件*/ 
 
 /* for  loggging information 创建个临时表格来保持*/ 
 CREATE TEMPORARY TABLE infologs ( 
 Id int(11) NOT NULL AUTO_INCREMENT, 
 Msg varchar(255) NOT NULL, 
 PRIMARY KEY (Id) 
 ); 
 
 OPEN  cur_product; /*Second: Open the cursor 接着使用OPEN打开游标*/ 
 FETCH  cur_product INTO prd_code; /*Third: now you can Fetch the row 把第一行数据写入变量中,游标也随之指向了记录的第一行*/ 
 
 REPEAT 
 
 SELECT  quantity INTO quantity_in_stock 
 FROM  products 
 WHERE  code = prd_code; 
  
 IF  quantity_in_stock < 100 THEN 
 INSERT  INTO infologs(msg) 
 VALUES  (prd_code); 
 END  IF; 
 FETCH  cur_product INTO prd_code; 
 
 UNTIL  no_more_products = 1 
 END REPEAT; 
 CLOSE  cur_product;  /*Finally: cursor need be closed 用完后记得用CLOSE把资源释放掉*/ 
 SELECT *  FROM infologs; 
 DROP TABLE  infologs; 
END $$ 
 
DELIMITER ; 

下面是最终的结果:

<img src="http://www.111cn.net /uploads/201208/18/1345302174_3501.png" alt=""> 

时间: 2024-08-30 04:45:22

Mysql 存储过程的学习笔记的相关文章

mysql 存储过程语法学习笔记

今天又把mysql存储过程学习了下,大家先看以下代码: 对语法不懂的朋友,可以详细看下语法结构.  代码如下 复制代码 CREATE PROCEDURE and CREATE FUNCTION Syntax CREATE     [DEFINER = { user | CURRENT_USER }]     PROCEDURE sp_name ([proc_parameter[,...]])     [characteristic ...] routine_body CREATE     [DE

MySQL定时器EVENT学习笔记

 本文为大家介绍下MySQL定时器EVENT,要使定时起作用 MySQL的常量GLOBAL event_scheduler必须为on或者是1,感兴趣的朋友可以了解下 要使定时起作用 MySQL的常量GLOBAL event_scheduler必须为on或者是1    -- 查看是否开启定时器  SHOW VARIABLES LIKE '%sche%';    -- 开启定时器 0:off 1:on  SET GLOBAL event_scheduler = 1;    -- 创建事件  --每隔

Mysql源码学习笔记 偷窥线程_Mysql

感觉代码有些凌乱,注释代码都写的比较随意,好像没有什么统一的规范,不同的文件中代码风格也有差异,可能Mysql经过了很多牛人的手之后,集众牛人之长吧.也可能是我见识比较浅薄,适应了自己的代码风格,井底之蛙了,总之还是怀着敬畏的心情开始咱的源码之旅吧.本人菜鸟,大神轻拍. Mysql可以启动起来了,应该怎么学习呢?总不能从main开始一步一步的看吧,Mysql作为比较底层的大型软件,涉及到数据库实现的方方面面,没有厚实的数据库理论基础和对Mysql各个模块相当的熟悉,从main开始势必会把自己引入

mysql数据库入门学习笔记(1/2)

数据库一直没怎么重视,前段时间看了看mysql的基础知识,不看不知道,一看吓一跳,很多基础都竟然不知道,一直傻傻的用一些简单的.笨笨的方法,看了之后原来竟是如此如此,生活如此多娇,以前看不懂的,现在也懂点了,以前看到就头晕的,现在不晕了,发现一个奇怪的现象,应该很多人都有吧,当学一种知识的时候,而当时确实又是学不会.学不好的时候,随着时间的慢慢推移,再回过头来看的时候,发现比以前容易接受得多了--难怪这么多人到快挂的时候才后悔,不扯这么多了,把记录的笔记分享出来,方便日后查悦. 一.data数据

MYSQL事务处理之学习笔记

mysql事务处理的几个步骤: 1.关闭自动提交 2.开启事务处理 3.有异常就自动抛出异常提示再回滚 4.开启自动提交 注意:mysql只有这个InnoDB驱动是支持事务处理的,默认MyIsAM驱动不支持. 由于项目设计里面,牵扯到了金钱的转移,于是就要用到MYSQL的事务处理,来保证一组处理结果的正确性.用了事务,就不可避免的要牺牲一部分速度,来保证数据的正确性. 只有InnoDB支持事务 事务 ACID Atomicity(原子性).Consistency(稳定性).Isolation(隔

MySQL Group Replication 学习笔记

作者简介 刘伟  云和开创高级顾问 题记:group replication作为mysql官方,在5.7版本阶段开发的,innodb的分布式数据库架构,从发布开始就有很多关注,下文是我对目前为止的材料以及实验的一些总结. 主要资料来源是官方blog:http://mysqlhighavailability.com/ group replication架构 group replication(后文简称GR)实现的分布式数据库架构,底层的分布式基础是Paxos(出于行文限制,此处不单独交代Paxos

MySql官方手册学习笔记2 MySql的模糊查询和正则表达式_Mysql

SQL模式匹配允许你使用"_"匹配任何单个字符,而"%"匹配任意数目字符(包括零字符).在 MySQL中,SQL的模式默认是忽略大小写的.下面给出一些例子.注意使用SQL模式时,不能使用=或!=:而应使用LIKE或NOT LIKE比较操作符. 要想找出以"b"开头的名字:   mysql> SELECT * FROM pet WHERE name LIKE 'b%'; +--------+--------+---------+------+

MySql官方手册学习笔记1 MySql简单上手_Mysql

连接与断开服务器 连接服务器通常需要提供一个MySQL用户名并且很可能需要一个 密码.如果服务器运行在登录服务器之外的其它机器上,还需要指定主机名: shell> mysql -h host -u user -p Enter password: ******** host代表MySQL服务器运行的主机名,user代表MySQL账户用户名,******** 代表你的密码. 如果有效,你应该看见mysql>提示符后的一些介绍信息: shell> mysql -h host -u user -

MySQL索引操作命令学习笔记

mysq索引类型:普通索引.唯一索引和主索引 1. 普通索引 普通索引(由关键字KEY或INDEX定义的索引)的唯一任务是加快对数据的访问速度.因此,应该只为那些最经常出现在查询条件(WHERE column = -)或排序条件(ORDER BY column)中的数据列创建索引.只要有可能,就应该选择一个数据最整齐.最紧凑的数据列(如一个整数类型的数据列)来创建索引. 2. 唯一索引 普通索引允许被索引的数据列包含重复的值.比如说,因为人有可能同名,所以同一个姓名在同一个"员工个人资料&quo