先放入mysql存储过程,便于大家了解一下存储过程的整体代码结构:
CREATE PROCEDURE `get_branch_path`(IN company CHAR(32))
BEGIN
DECLARE _branchid CHAR(32) ;
DECLARE _branchpath LONGTEXT;
DECLARE _currentid CHAR(32);
DECLARE fetchSeqOK boolean;
DECLARE cur1 CURSOR FOR SELECT branchid FROM t_branch WHERE companyid=company;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET fetchSeqOK=TRUE;
SET fetchSeqOK=FALSE;
DROP TEMPORARY TABLE IF EXISTS temp_table;
CREATE TEMPORARY TABLE IF NOT EXISTS temp_table (
branchid CHAR(32),
branchpath LONGTEXT
);
OPEN cur1;
FETCH cur1 INTO _currentid;
fetchSeqLoop:LOOP
IF fetchSeqOK THEN
LEAVE fetchSeqLoop;
ELSE
SET _branchid = _currentid;
SET _branchpath = NULL;
CALL generate_branch_path(_currentid, _branchpath);
INSERT INTO temp_table VALUES(_branchid, _branchpath);
FETCH cur1 INTO _currentid;
END IF;
END LOOP;
CLOSE cur1;
SELECT branchid,branchpath FROM temp_table;
DROP TABLE temp_table;
END
CREATE PROCEDURE `generate_branch_path`(INOUT `_subid` varchar(255),INOUT `_subpath` longtext)
BEGIN
DECLARE _path LONGTEXT;
DECLARE _parentid CHAR(32);
DECLARE fetchSeqOK boolean;
DECLARE cur2 CURSOR FOR SELECT `name`,parentid FROM t_branch WHERE branchid=_subid;
SET @@max_sp_recursion_depth = 20;
OPEN cur2;
FETCH cur2 INTO _path,_parentid;
IF( LEFT(_parentid,1) <> 0 ) THEN
SET _subid = _parentid;
IF (_subpath IS NULL) THEN
SET _subpath = _path;
ELSE
SET _subpath = CONCAT(_path,'/',_subpath);
END IF;
CALL generate_branch_path(_subid,_subpath);
ELSE
IF (_subpath IS NULL) THEN
SET _subpath = _path;
ELSE
SET _subpath = CONCAT(_path,'/',_subpath);
END IF;
END IF;
END
上述两个存储过程所需要的数据表及测试数据:
CREATE TABLE `t_branch` (
`branchid` char(32) NOT NULL,
`companyid` char(32) NOT NULL,
`name` varchar(50) NOT NULL,
`parentid` char(32) NOT NULL,
`sortid` int(11) NOT NULL,
`remark` varchar(200) DEFAULT NULL,
`isshare` int(11) DEFAULT NULL,
`lastupdatetime` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
`createtime` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00',
PRIMARY KEY (`branchid`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
INSERT INTO `t_branch` VALUES ('402880ff2d6f871a012d6f871cf30000','402880ff2d5f53cd012d5f53d43d0000','销售部门','0','2','就是湖北销售部门!','0','2011-01-11 18:13:35','2011-01-10 18:46:32'),
('402880ff2d6f871a012d6f8788210001','402880ff2d5f53cd012d5f53d43d0000','hbdev','402880ff2d744a06012d74531f8e0002','1','就是湖北研发','1','2011-01-11 17:16:42','2011-01-10 18:47:00'),
('402880ff2d6f871a012d6f8816f30002','402880ff2d5f53cd012d5f53d43d0000','abc team','402880ff2d6f871a012d6f8788210001','2','就是 abc team!','1','2011-01-11 18:21:34','2011-01-10 18:47:36'),
('402880ff2d744a06012d745231660000','402880ff2d5f53cd012d5f53d43d0000','人力资源部','0','3','就是湖北人力资源部!','0','2011-01-11 18:18:11','2011-01-11 17:06:47'),
('402880ff2d744a06012d7452930e0001','402880ff2d5f53cd012d5f53d43d0000','市场部','0','4','就是湖北市场部!','0','2011-01-11 18:18:11','2011-01-11 17:07:12'),
('402880ff2d744a06012d74531f8e0002','402880ff2d5f53cd012d5f53d43d0000','PTC','0','1','就是EFG!','0','2011-01-11 17:17:23','2011-01-11 17:07:48'),
('402880ff2d749155012d7492e8e70000','402880ff2d5f53cd012d5f53d43d0000','HDK team','402880ff2d6f871a012d6f8788210001','1','就是HDK team!','0','2011-01-11 18:17:28','2011-01-11 18:17:28'),
('ff8080812e3792bb012e50492fad0018','402880ff2d5f53cd012d5f53d43d0000','新部门','402880ff2d6f871a012d6f871cf30000','1','','0','2011-02-23 10:11:37','2011-02-23 10:11:37');
1.1存储过程代码结构:
CREATE PROCEDURE 存储过程名(参数列表,有三种类型:IN,OUT,INOUT)
BEGIN
1.变量和条件声明
2. Cursor声明
3. Handler声明
4. 程序代码
END
注意:
由括号包围的参数列必须总数存在的。如果没有参数,也要使用一个空参数列()。每个参数默认都是一个IN参数,可在参数名之间加入OUT,INOUT等关键字指定为其他类型。
变量和条件声明不需放在Cursor声明等代码块之前,否则该存储过程编译不能通过。
1.2变量声明
DECLARE _branchid CHAR(32) ;
DECLARE 关键字
_branchid 变量名
CHAR(32) 变量类型
1.3指针和Handler声明
定义游标
cur1 CURSOR FOR SELECT branchid FROM t_branch WHERE companyid=company;
使用游标
open cur1;
fetch数据
FETCH cur1 INTO _currentid;
关闭游标
close cur1;
用到游标cur1,都会离不开循环语句。
一般使用Loop和while来进行循环语句的编写。
这里使用Loop为例
fetchSeqLoop:LOOP
fetch cur1 into _currentid;
end Loop;
现在是死循环,还没有退出的条件,那么在这里和oracle有区别,OraclePL/SQL的指针有个隐性变量%notfound,
Mysql是通过一个Error handler的声明来进行判断的,
DECLARE CONTINUE HANDLER FOR NOT FOUND SET fetchSeqOK=TRUE;
在Mysql里当游标遍历溢出时,会出现一个预定义的NOT FOUND的Error,我们处理这个Error并定义一个continue的handler就可以了,
关于Mysql Error handler可以查询Mysql手册。定义一个flag,在NOT FOUND,标示Flag,在Loop里以这个flag为结束循环的判断就可以了。
具体代码可以参考上面的存储过程:get_branch_path();
注意:在循环语句中,记得使用FETCH cur1 into _currentid来进行指针的数据移动,否则指针会一直指向你初次赋值的地方,而不指向下一个值。
1.4程序代码
根据上述定义的变量,临时表,指针等运用循环语句,IF/ELSE语句,函数等内容完成一定的业务逻辑。
IF语句的结构:
IF 逻辑表达式 THEN
程序语句;
ELSE
程序语句;
END IF;
WHILE语句的结构:
WHILE 逻辑表达式 DO
程序语句;
END WHILE;
LOOP语句的结构:
LOOP
程序语句;
END LOOP;
可以给代码块加lebel,这样END匹配比较直观,还可以用LEAVE语句来终结代码块:
fetchSeqLoop:LOOP
IF fetchSeqOK THEN
LEAVE fetchSeqLoop;
ELSE
程序语句;
END IF;
END LOOP;
2.1存储过程调用
CALL generate_branch_path(_currentid, _branchpath);
存储过程中的参数有三种IN,OUT,INOUT.具体用法可以看看下面的这篇文章,就能够明白:
http://www.blogjava.net/nonels/archive/2009/04/22/233324.html
2.2存储过程的结果集返回
上述存储过程中,创建了一个临时表temp_table,用于存储调用方(持久层中间件:hibenate,ibatis,JDBC)所需要的结果集。如果不考虑临时表的回收问题,在调用方可以在调用存储过程之后,再直接用sql语句查询该临时表获取结果集。但考虑到临时表的回收问题,需要在存储过程结束时,删除该临时表,并返回该结果集。使用如下代码即可达到目的。
SELECT branchid,branchpath FROM temp_table;
DROP TABLE temp_table;
在有了上面的SELECT语句之后,在DAO层调用存储过程之后,通过代码就可以获取结果集了。
使用JDBC等接口代码完成结果集的返回。
String url = "jdbc:mysql://127.0.0.1:3306/test";
try {
DriverManager.registerDriver(new com.mysql.jdbc.Driver());
Connection conn = DriverManager.getConnection(url, "root","");
CallableStatement stmt = conn.prepareCall("{call xx()}");
stmt.execute();
ResultSet rs = (ResultSet)stmt.getResultSet();
while(rs.next()){
System.out.print (rs.getString(1));
System.out.print (" , ");
System.out.println (rs.getString(2));
}
} catch (SQLException e) {
e.printStackTrace();
}
行了,关于mysql总结的经验主要就是这些了,上述代码很多借鉴了其他的一些文章,有雷同之处还望大家见谅。关于上述贴出的存储过程,数据表等是可以编译通过,并运行的。大家想学习的话,可以拷贝下来测试一下。
分享到:
相关推荐
### MySQL存储过程实例教程 #### 存储过程概念与优势 存储过程,作为数据库中一种预编译的SQL语句集合,旨在实现特定功能并存储于数据库内,用户仅需指定其名称及必要参数即可调用执行。这种设计极大地简化了...
MYSQL 存储过程 实例,要的自己下,分有点贵哦。
MySQL存储过程实例教程 MySQL存储过程是数据库存储的一个重要的功能,它允许控制数据的访问方式,提供了灵活的编程方式,提高了数据库的处理速度和灵活性。本教程将详细介绍 MySQL 存储过程的概念、优点、创建和...
mysql存储过程实例详解
根据给定的信息,我们可以深入探讨PHP与MySQL存储过程的相关知识点,包括如何在MySQL中使用`CONCAT`函数、创建存储过程以及如何通过PHP脚本来调用这些存储过程。 ### 使用 CONCAT 函数 #### 标题中的示例 ```sql ...
在这个实例中,我们看到一个名为`Sum_wage`的存储过程,它的主要目的是对`ProWage`表中的工资进行加薪操作。 首先,存储过程的创建使用了`CREATE PROCEDURE`语句,定义了一个名为`Sum_wage`的过程,并接受三个参数...
MySQL存储过程是数据库管理系统提供的一种高级程序设计语言,允许用户在数据库中封装一系列复杂的操作,以便重复使用。在MySQL 5.0及后续版本中,存储过程被引入,极大地提升了数据库管理和应用程序的效率。本教程将...
### MySQL存储过程详解 #### 一、存储过程概述 存储过程是一种特殊类型的SQL代码集合,它们预先被编译并存储在数据库服务器上。用户可以通过指定存储过程名称并提供必要的参数来执行这些存储过程。这种机制提供了...
### PHP调用MySQL存储过程实例 在PHP中调用MySQL存储过程,通常使用`mysqli`扩展。在创建了存储过程后,我们可以通过PHP脚本来调用这些存储过程。以下是一个获取MySQL当前版本号的存储过程调用实例: ```sql ...
本资源结合实例实现一个复杂的存储过程,存储过程中有用到游标、临时表、循环、递归等知识,sql文件附有实例数据表创建的sql语句。
本实例展示了如何在MySQL存储过程中实现异常处理,以捕获并处理可能出现的错误。 首先,我们注意到在创建存储过程`myProc`时,使用了`delimiter $$`来改变MySQL客户端的语句分隔符,这是为了在存储过程中使用多个...
本文实例讲述了mysql存储过程之错误处理。分享给大家供大家参考,具体如下: 当存储过程中发生错误时,重要的是适当处理它,例如:继续或退出当前代码块的执行,并发出有意义的错误消息。其中mysql提供了一种简单的...