免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 6373 | 回复: 8
打印 上一主题 下一主题

【已解决】存储过程中的用户变量和局部变量到底什么区别? [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2013-10-29 10:34 |只看该作者 |倒序浏览
本帖最后由 chinafenghao 于 2013-10-30 13:58 编辑

发现在存储过程中用prepare语句是不能使用局部变量的,这到底是为啥,mysql出于什么目的设计了用户变量?它和局部变量的区别在哪里

论坛徽章:
8
CU大牛徽章
日期:2013-09-18 15:20:48CU大牛徽章
日期:2013-09-18 15:20:58CU大牛徽章
日期:2013-09-18 15:21:06CU大牛徽章
日期:2013-09-18 15:21:12CU大牛徽章
日期:2013-09-18 15:21:17天秤座
日期:2013-10-30 14:01:03摩羯座
日期:2013-11-29 18:02:31luobin
日期:2016-06-17 17:46:36
2 [报告]
发表于 2013-10-30 13:58 |只看该作者
一、局部变量。
局部变量一般用在sql语句块中,比如存储过程的begin/end。其作用域仅限于该语句块,在该语句块执行完毕后,局部变量就消失了。
局部变量一般用declare来声明,可以使用default来说明默认值。
例如在存储过程中定义局部变量:
drop procedure if exists add;
create procedure add
(
    in a int,
    in b int
)
begin
    declare c int default 0;
    set c = a + b;
    select c as c;
end;

在上述存储过程中定义的变量c就是局部变量

二、用户变量。
用户变量的作用域要比局部变量要广。用户变量可以作用于当前整个连接,但是当当前连接断开后,其所定义的用户变量都会消失。
用户变量使用如下的方式定义:
    @变量名
对用户变量赋值有两种方式,一种是直接用"="号,另一种是用":="号。其区别在于使用set命令对用户变量进行赋值时,两种方式都可以使用;当使用select语句对用户变量进行赋值时,只能使用":="方式,因为在select语句中,"="号被看作是比较操作符。
示例程序如下:
drop procedure if exists math;
create procedure math
(
    in a int,
    in b int
)
begin
    set @var1 = 1;
    set @var2 = 2;
    select @sum:=(a + b) as sum, @dif:=(a - b) as dif;
end;

mysql> call math(3, 4);
+------+------+
| sum  | dif  |
+------+------+
|    7 |   -1 |
+------+------+
1 row in set (0.00 sec)

Query OK, 0 rows affected (0.00 sec)

mysql> select @var1; //var1为用户变量
+-------+
| @var1 |
+-------+
| 1     |
+-------+
1 row in set (0.00 sec)

mysql> select @var2; //var2为用户变量
+-------+
| @var2 |
+-------+
| 2     |
+-------+
1 row in set (0.00 sec)

@abcbuzhiming

论坛徽章:
1
综合交流区版块每日发帖之星
日期:2015-10-14 06:20:00
3 [报告]
发表于 2013-10-31 06:48 |只看该作者
这句错了:'用户变量可以作用于当前整个连接,但是当当前连接断开后,其所定义的用户变量都会消失。'

事实是,当前连接断开后,@var1 @var2 以及math过程都被存储起来;再次连上后,可以直接call math(3, 4);select @var1;select @var2;

我猜测是当mysqld进程退出后,这些存储过程和变量才会消失,需要重新定义。

论坛徽章:
2
酉鸡
日期:2014-02-19 09:11:08摩羯座
日期:2014-05-23 10:16:16
4 [报告]
发表于 2013-10-31 09:05 |只看该作者
2楼3楼学习了

论坛徽章:
0
5 [报告]
发表于 2013-11-01 14:13 |只看该作者
fly3ds 发表于 2013-10-31 06:48
这句错了:'用户变量可以作用于当前整个连接,但是当当前连接断开后,其所定义的用户变量都会消失。'

事 ...

我有一个问题,如果用户变量的作用域如此大的话,那么它是怎么避免变量名污染这个问题的,假设一个用户连接在此次连接调用了两个存储过程,两个存储过程中有同名的用户变量,这会引发类似线程安全问题吗

论坛徽章:
1
综合交流区版块每日发帖之星
日期:2015-10-14 06:20:00
6 [报告]
发表于 2013-11-01 14:19 |只看该作者
本帖最后由 fly3ds 于 2013-11-01 14:23 编辑

回复 5# abcbuzhiming

      编写存储过程的人要自己避免。如果你学过或者做一些程序设计,会发现在任何程序设计环境里都是这样,需要自己避免变量名重复,函数名重复的问题,如果重复了编译器会报错。MySQL报不报错我就没试过了。

     或者你尽可能用局部变量。

论坛徽章:
0
7 [报告]
发表于 2013-11-01 14:29 |只看该作者
fly3ds 发表于 2013-11-01 14:19
回复 5# abcbuzhiming

      编写存储过程的人要自己避免。如果你学过或者做一些程序设计,会发现在任何 ...

要能用我早就用局部变量了,问题是prepare语句压根就不支持局部变量

论坛徽章:
1
综合交流区版块每日发帖之星
日期:2015-10-14 06:20:00
8 [报告]
发表于 2013-11-01 14:37 |只看该作者
回复 7# abcbuzhiming


    你没看见二楼文章里的declare c嘛?试试看。

论坛徽章:
0
9 [报告]
发表于 2013-11-02 12:09 |只看该作者
fly3ds 发表于 2013-11-01 14:37
回复 7# abcbuzhiming

局部变量不能用于prepare语句,尤其不能用于参数。我早就试过了
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP