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 相关文章推荐
php中的数组操作函数整理
Aug 18 PHP
php通用防注入程序 推荐
Feb 26 PHP
php产生随机数的两种方法实例代码 输出随机IP
Apr 08 PHP
查找php配置文件php.ini所在路径的二种方法
May 26 PHP
使用php批量删除数据库下所有前缀为prefix_的表
Jun 09 PHP
详解PHP序列化反序列化的方法
Oct 27 PHP
php usort 使用用户自定义的比较函数对二维数组中的值进行排序
May 02 PHP
PHP基于双向链表与排序操作实现的会员排名功能示例
Dec 26 PHP
php 字符串中是否包含指定字符串的多种方法
Apr 12 PHP
PHP连接sftp并下载文件的方法教程
Aug 26 PHP
YII2框架中添加自定义模块的方法实例分析
Mar 18 PHP
php去除deprecated的实例方法
Nov 17 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
php邮件发送,php发送邮件的类
2011/03/24 PHP
php管理nginx虚拟主机shell脚本实例
2014/11/19 PHP
jquery与google map api结合使用 控件,监听器
2010/03/04 Javascript
javascript检测对象中是否存在某个属性判断方法小结
2013/05/19 Javascript
php 中序列化和json使用介绍
2013/07/08 Javascript
JavaScript 32位整型无符号操作示例
2013/12/08 Javascript
jQuery函数的第二个参数获取指定上下文中的DOM元素
2014/05/19 Javascript
浅谈EasyUI中Treegrid节点的删除
2015/03/01 Javascript
js表格排序实例分析(支持int,float,date,string四种数据类型)
2015/05/06 Javascript
关于微信上网页图片点击全屏放大效果
2016/12/19 Javascript
node.js入门学习之url模块
2017/02/25 Javascript
jQuery插件echarts实现的多折线图效果示例【附demo源码下载】
2017/03/04 Javascript
JS如何判断浏览器类型和详细区分IE各版本浏览器
2017/03/04 Javascript
9种改善AngularJS性能的方法
2017/11/28 Javascript
vue2 全局变量的设置方法
2018/03/09 Javascript
jquery分页插件pagination使用教程
2018/10/23 jQuery
基于layui table返回的值的多级嵌套的解决方法
2019/09/19 Javascript
VUEX-action可以修改state吗
2019/11/19 Javascript
利用JS如何获取form表单数据
2019/12/19 Javascript
[02:46]2014DOTA2国际邀请赛 选手为你解读比赛MVP充满梦想
2014/07/09 DOTA
一篇文章了解Python中常见的序列化操作
2019/06/20 Python
Python基于pip实现离线打包过程详解
2020/05/15 Python
python用tkinter实现一个gui的翻译工具
2020/10/26 Python
scrapy处理python爬虫调度详解
2020/11/23 Python
详解python的xlwings库读写excel操作总结
2021/02/26 Python
中专毕业生自荐信
2013/11/16 职场文书
九年级物理教学反思
2014/01/29 职场文书
仓库管理员岗位职责
2014/03/19 职场文书
买卖协议书范本
2014/04/21 职场文书
秋冬农业生产标语
2014/10/09 职场文书
离婚协议书怎么写
2015/01/26 职场文书
2015年幼儿园教研活动总结
2015/03/25 职场文书
2015年班长个人工作总结
2015/04/03 职场文书
2015年学校禁毒工作总结
2015/05/27 职场文书
2015暑期工社会实践报告
2015/07/13 职场文书
2019送给家人们的中秋节祝福语
2019/08/15 职场文书