mysql中存储过程、函数的一些问题


Posted in PHP onFebruary 14, 2007

最近写一些mysql的存储过程和函数,发现网上比较有价值的文档很少,大都是照着手册上抄来的,有些实际问题解决不了,比如用变量作表名。

经过反复调试,总算找到解决办法,一下是一些简单的记录,比较零碎。部分内容转自http://my.opera.com/Dereky/blog/show.dml/322997

1.用变量做表名:

简单的用set或者declare语句定义变量,然后直接作为sql的表名是不行的,mysql会把变量名当作表名。在其他的sql数据库中也是如此,mssql的解决方法是将整条sql语句作为变量,其中穿插变量作为表名,然后用sp_executesql调用该语句。

这在mysql5.0之前是不行的,5.0之后引入了一个全新的语句,可以达到类似sp_executesql的功能(仅对procedure有效,function不支持动态查询):

PREPARE stmt_name FROM preparable_stmt;
EXECUTE stmt_name [USING @var_name [, @var_name] ...];
{DEALLOCATE | DROP} PREPARE stmt_name;

为了有一个感性的认识,
下面先给几个小例子:

mysql> PREPARE stmt1 FROM 'SELECT SQRT(POW(?,2) + POW(?,2)) AS hypotenuse';
mysql> SET @a = 3;
mysql> SET @b = 4;
mysql> EXECUTE stmt1 USING @a, @b;
+------------+
| hypotenuse |
+------------+
| 5 |
+------------+
mysql> DEALLOCATE PREPARE stmt1;

mysql> SET @s = 'SELECT SQRT(POW(?,2) + POW(?,2)) AS hypotenuse';
mysql> PREPARE stmt2 FROM @s;
mysql> SET @a = 6;
mysql> SET @b = 8;
mysql> EXECUTE stmt2 USING @a, @b;
+------------+
| hypotenuse |
+------------+
| 10 |
+------------+
mysql> DEALLOCATE PREPARE stmt2;

如果你的MySQL 版本是 5.0.7 或者更高的,你还可以在 LIMIT 子句中使用它,示例如下:
mysql> SET @a=1;mysql> PREPARE STMT FROM "SELECT * FROM tbl LIMIT ?";
mysql> EXECUTE STMT USING @a;
mysql> SET @skip=1; SET @numrows=5;
mysql> PREPARE STMT FROM "SELECT * FROM tbl LIMIT ?, ?";
mysql> EXECUTE STMT USING @skip, @numrows;

使用 PREPARE 的几个注意点:
A:PREPARE stmt_name FROM preparable_stmt;预定义一个语句,并将它赋给 stmt_name ,tmt_name 是不区分大小写的。
B: 即使 preparable_stmt 语句中的 ? 所代表的是一个字符串,你也不需要将 ? 用引号包含起来。
C: 如果新的 PREPARE 语句使用了一个已存在的 stmt_name ,那么原有的将被立即释放! 即使这个新的 PREPARE 语句因为错误而不能被正确执行。
D: PREPARE stmt_name 的作用域是当前客户端连接会话可见。
E: 要释放一个预定义语句的资源,可以使用 DEALLOCATE PREPARE 句法。
F: EXECUTE stmt_name 句法中,如果 stmt_name 不存在,将会引发一个错误。
G: 如果在终止客户端连接会话时,没有显式地调用 DEALLOCATE PREPARE 句法释放资源,服务器端会自己动释放它。
H: 在预定义语句中,CREATE TABLE, DELETE, DO, INSERT, REPLACE, SELECT, SET, UPDATE, 和大部分的 SHOW 句法被支持。
I: PREPARE 语句不可以用于存储过程,自定义函数!但从 MySQL 5.0.13 开始,它可以被用于存储过程,仍不支持在函数中使用!

下面给个示例:
CREATE PROCEDURE `p1`(IN id INT UNSIGNED,IN name VARCHAR(11))
BEGIN lable_exit:
BEGIN
SET @SqlCmd = 'SELECT * FROM tA ';
IF id IS NOT NULL THEN
SET @SqlCmd = CONCAT(@SqlCmd , 'WHERE id=?');
PREPARE stmt FROM @SqlCmd;
SET @a = id;
EXECUTE stmt USING @a;
LEAVE lable_exit;
END IF;
IF name IS NOT NULL THEN
SET @SqlCmd = CONCAT(@SqlCmd , 'WHERE name LIKE ?');
PREPARE stmt FROM @SqlCmd;
SET @a = CONCAT(name, '%');
EXECUTE stmt USING @a;
LEAVE lable_exit;
END IF;
END lable_exit;
END;
CALL `p1`(1,NULL);
CALL `p1`(NULL,'QQ');
DROP PROCEDURE `p1`;

了解了PREPARE的用法,再用变量做表名就很容易了。不过在实际操作过程中还发现其他一些问题,比如变量定义,declare变量和set @var=value变量的用法以及参数传入的变量。

测试后发现,set @var=value这样定义的变量直接写在字符串中就会被当作变量转换,declare的变量和参数传入的变量则必须用CONCAT来连接。具体的原理没有研究。

EXECUTE stmt USING @a;这样的语句USING后面的变量也只能用set @var=value这种,declare和参数传入的变量不行。

另外php调用mysql存储过程的时候也碰到很多问题,总是出现PROCEDURE p can't return a result set in the given context这样的问题。

PHP 相关文章推荐
Uchome1.2 1.5 代码学习 common.php
Apr 24 PHP
PHP 利用Mail_MimeDecode类提取邮件信息示例
Jan 26 PHP
php上传文件问题汇总
Jan 30 PHP
PHP实现HTML页面静态化的方法
Nov 04 PHP
php微信公众平台开发(四)回复功能开发
Dec 06 PHP
PHP函数rtrim()使用中的怪异现象分析
Feb 24 PHP
php模仿qq空间或朋友圈发布动态、评论动态、回复评论、删除动态或评论的功能(中)
Jun 11 PHP
php实现生成code128条形码的方法详解
Jul 19 PHP
thinkPHP5框架实现基于ajax的分页功能示例
Jun 12 PHP
PHP中散列密码的安全性分析
Jul 26 PHP
PHP使用PDO实现mysql防注入功能详解
Dec 20 PHP
实例讲解PHP表单
Jun 10 PHP
让PHP支持页面回退的两种方法[转]
Feb 14 #PHP
浅析PHP水印技术
Feb 14 #PHP
解决GD中文乱码问题
Feb 14 #PHP
使用apache模块rewrite_module (转)
Feb 14 #PHP
用PHP的ob_start();控制您的浏览器cache!
Feb 14 #PHP
谈谈PHP的输入输出流
Feb 14 #PHP
修改了一个很不错的php验证码(支持中文)
Feb 14 #PHP
You might like
Fine Uploader文件上传组件应用介绍
2013/01/06 PHP
is_uploaded_file函数引发的不能上传文件问题
2013/10/29 PHP
php文件上传的例子及参数详解
2013/12/12 PHP
php无限极分类递归排序实现方法
2014/11/11 PHP
php对数组内元素进行随机调换的方法
2015/05/12 PHP
php cookie工作原理与实例详解
2016/07/18 PHP
2017年最新PHP经典面试题目汇总(上篇)
2017/03/17 PHP
PHP iconv()函数字符编码转换的问题讲解
2019/03/22 PHP
jQuery实战之品牌展示列表效果
2011/04/10 Javascript
js confirm()方法的使用方法实例
2013/07/13 Javascript
JS增加行复制行删除行的实现代码
2013/11/09 Javascript
angularJS结合canvas画图例子
2015/02/09 Javascript
深入理解jquery自定义动画animate()
2016/05/24 Javascript
原生js仿浏览器滚动条效果
2017/03/02 Javascript
关于meta viewport中target-densitydpi属性详解(推荐)
2017/08/18 Javascript
Three.js 再探 - 写一个微信跳一跳极简版游戏
2018/01/04 Javascript
jQuery中内容过滤器简单用法示例
2018/03/31 jQuery
微信小程序实现上传图片功能
2018/05/28 Javascript
[00:23]魔方之谜解锁款式
2018/12/20 DOTA
python操作xml文件示例
2014/04/07 Python
轻量级的Web框架Flask 中模块化应用的实现
2017/09/11 Python
Anaconda2 5.2.0安装使用图文教程
2018/09/19 Python
对Python3中bytes和HexStr之间的转换详解
2018/12/04 Python
python 计算两个列表的相关系数的实现
2019/08/29 Python
Python3爬虫关于识别检验滑动验证码的实例
2020/07/30 Python
Python在字符串中处理html和xml的方法
2020/07/31 Python
台湾最大银发乐活百货:乐龄网
2018/05/21 全球购物
职务说明书范文
2014/05/07 职场文书
公司试用期员工自我评价
2014/09/17 职场文书
政府领导干部个人对照检查材料思想汇报
2014/09/24 职场文书
2014年信访维稳工作总结
2014/12/08 职场文书
寒假致家长的一封信
2015/10/10 职场文书
ROS系统将python包编译为可执行文件的简单步骤
2021/07/25 Python
使用canvas对video视频某一刻截图功能
2021/09/25 HTML / CSS
世界十大评分最高的动漫,CLANNAD上榜,第八赚足人们眼泪
2022/03/18 日漫
Spring Cloud OAuth2实现自定义token返回格式
2022/06/25 Java/Android