平时写 SQL 查询, 存储过程都是凭着感觉来, 没有探究过 SQL 的具体语法, 一直都是按 c# 那一套往 SQL 上模仿, 前几天项目中碰到一个问题引起了我对 declare 定义变量的作用域的兴趣.
大家都知道 c# 中的局部变量, 在 if 中如果我们定义一个变量的话他的作用到 if 结束为止, if 外是不识别这个变量的, else 里都不能使用, 简单的写一下.
- if (true)
- {
- Int32 i = 1;
- Console.WriteLine(i);
- }
这个 i 的作用域就是 if 里面, 如果我们在 if 外面用这个变量
- if (true)
- {
- Int32 i = 1;
- Console.WriteLine(i);
- }
- Console.WriteLine(i);
那第二条输出语句会报错
The name 'i' does not exist in the current context
说明已经出了 i 的作用域了.
那么我们要是在 sql 写这么一段代码会是什么情况呢? 首先写在 if 内
- IF 1=1
- BEGIN
- DECLARE @test VARCHAR
- SET @test='1'
- PRINT 'in if:'+@test
- END
运行看结果输出 in if:1 这是可以预想的结果. 那我们在 if 外面使用变量 @test 试试.
- IF 1=1
- BEGIN
- DECLARE @test VARCHAR
- SET @test='1'
- PRINT 'in if:'+@test
- END
- PRINT 'out if:'+@test
这样会是什么结果呢, 不知道大家怎么想的, 以我的大脑顺势就想到这应该报错啊, 出了变量的作用域了. 实际结果不仅没报错而且 @test 的值还在.
- in if:1
- out if:1
看见这个结果当时我很郁闷, SQL 太出人意料了.
在 SQL SERVER 2005 的帮助文档里关于 declare 的帮助里发现这么一句话, 备注的第三行 "局部变量的作用域是其被声明时所在批处理"
Msdn 的地址: http://msdn.microsoft.com/zh-cn/library/ms188927.aspx
这行字在这么一大篇中还真挺不引人瞩目.
现在我们知道原来 declare 变量的作用域是所在的批处理, if 阻断不了它的作用域, 那上面我们的代码 if 内外的代码都在一个批处理中, 所以 @test 都是可用的且 if 里面设置的值还在.
下面我改造一下代码, SQL 中是以 GO 语句来区分批处理的
- IF 1=1
- BEGIN
- DECLARE @test VARCHAR
- SET @test='1'
- PRINT 'in if:'+@test
- END
- GO
- PRINT 'out if:'+@test
来源: http://www.bubuko.com/infodetail-2733837.html