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表单提交表单名称含有点号(.)则会被转化为下划线(_)
Dec 14 PHP
php获取参数的几种方法总结
Feb 18 PHP
PHP常用的缓存技术汇总
May 05 PHP
php实现复制移动文件的方法
Jul 29 PHP
php实现Mysql简易操作类
Oct 11 PHP
Laravel与CI框架中截取字符串函数
May 08 PHP
iOS自定义提示弹出框实现类似UIAlertView的效果
Nov 16 PHP
laravel实现分页样式替换示例代码(增加首、尾页)
Sep 22 PHP
thinkPHP5框架导出Excel文件简单操作示例
Aug 03 PHP
tp5(thinkPHP5)框架连接数据库的方法示例
Dec 24 PHP
tp5.0框架隐藏index.php入口文件及模块和控制器的方法分析
Feb 11 PHP
PHP 范围解析操作符(::)用法分析【访问静态成员和类常量】
Apr 14 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通过COM使用ADODB的简单例子
2006/12/31 PHP
PHP自定义函数获取URL中一级域名的方法
2016/08/23 PHP
php自定义排序uasort函数示例【二维数组按指定键值排序】
2019/06/19 PHP
laravel config文件配置全局变量的例子
2019/10/13 PHP
Chrome中模态对话框showModalDialog返回值问题的解决方法
2010/05/25 Javascript
jQuery学习笔记[1] jQuery中的DOM操作
2010/12/03 Javascript
复选框全选与全不选操作实现思路
2013/08/18 Javascript
JQueryiframe页面操作父页面中的元素与方法(实例讲解)
2013/11/19 Javascript
实现前后端数据交互方法汇总
2015/04/07 Javascript
js图片轮播特效代码分享
2015/09/07 Javascript
jQuery实现的placeholder效果完整实例
2016/08/02 Javascript
老生常谈Javascript中的原型和this指针
2016/10/09 Javascript
微信小程序实现点击按钮修改字体颜色功能【附demo源码下载】
2017/12/05 Javascript
vue中路由参数传递可能会遇到的坑
2017/12/07 Javascript
解决vue项目报错webpackJsonp is not defined问题
2018/03/14 Javascript
解决element UI 自定义传参的问题
2018/08/22 Javascript
jQuery实现点击图标div循环放大缩小功能
2018/09/30 jQuery
vuex实现的简单购物车功能示例
2019/02/13 Javascript
Vue.js中Line第三方登录api的实现代码
2020/06/29 Javascript
vue-router 控制路由权限的实现
2020/09/24 Javascript
Nuxt的动态路由和参数校验操作
2020/11/09 Javascript
vue集成一个支持图片缩放拖拽的富文本编辑器
2021/01/29 Vue.js
处理python中多线程与多进程中的数据共享问题
2019/07/28 Python
python模拟鼠标点击和键盘输入的操作
2019/08/04 Python
Pytorch 搭建分类回归神经网络并用GPU进行加速的例子
2020/01/09 Python
使用Keras预训练模型ResNet50进行图像分类方式
2020/05/23 Python
将一个文本文件的内容按倒序打印出来
2015/01/05 面试题
年终自我鉴定
2013/10/09 职场文书
大二学期个人自我评价
2014/01/13 职场文书
活动策划邀请函
2014/02/06 职场文书
化妆品店促销方案
2014/02/24 职场文书
祖国在我心中演讲稿450字
2014/09/05 职场文书
经费申请报告范文
2015/05/18 职场文书
建国大业观后感
2015/06/01 职场文书
MySQL提取JSON字段数据实现查询
2022/04/22 MySQL
MySQL中的全表扫描和索引树扫描
2022/05/15 MySQL