首页 > 代码库 > 【转】SQL SERVER 存储过程中变量的作用域
【转】SQL SERVER 存储过程中变量的作用域
今天遇到一个很有趣的事情,以前没有注意过,所以记下来。
先来看例子。
SET ANSI_NULLS ONGOSET QUOTED_IDENTIFIER ONGO CREATE PROCEDURE GetOrderBeforeDays @BeforDays INTASBEGIN IF @BeforDays < 0 BEGIN DECLARE @Today DATETIME SET @Today = GETDATE() DECLARE @Date DATETIME SET @Date = DATEADD(DAY,@BeforDays,@Today) SELECT * FROM Orders WHERE CONVERT(VARCHAR(10),OrderDate,110) = CONVERT(VARCHAR(10),@Date,110) END ELSE BEGIN SELECT * FROM Orders WHERE CONVERT(VARCHAR(10),OrderDate,110) = CONVERT(VARCHAR(10),@Today,110) ENDENDGO
这个存储过程创建时不会有什么问题,但实际执行时是不正确的,当参数大于0时并不能获取当天的数据。仔细看会发现@Today变量的定义在第一个IF语句中,但是在ELSE语句中竟然也可以使用,这与C#中的用法有所不同。
原来SQL SERVER中,声明变量的地方开始到声明变量的批处理或存储过程的结尾,因此在ELSE语句中也可以访问到IF语句中定义的变量。
但这会引起一些不必要的错误。如前边的例子中,虽然在ELSE语句中可以访问到定义的变量,但是并没有被赋值,所以执行时是查不到当天的定单的。
所以建议尽可能的把所有的变量和初始化都放在存储过程的最开始,一眼就可以看出定义了哪些变量,并赋了什么值。这样一来可以防止在大量的IF ELSE 语句中不小心重复定义相同的变量而引起不必要的麻烦,也可以避免像前边的例子中的错误
1 SET ANSI_NULLS ON 2 3 GO 4 5 SET QUOTED_IDENTIFIER ON 6 7 GO 8 9 10 11 CREATE PROCEDURE GetOrderBeforeDays12 13 @BeforDays INT14 15 AS16 17 BEGIN18 19 DECLARE @Today DATETIME20 21 SET @Today = GETDATE()22 23 DECLARE @Date DATETIME24 25 SET @Date = DATEADD(DAY,@BeforDays,@Today)26 27 IF @BeforDays < 028 BEGIN29 SELECT * FROM Orders WHERE CONVERT(VARCHAR(10),OrderDate,110) = CONVERT(VARCHAR(10),@Date,110)30 END31 ELSE32 BEGIN33 SELECT * FROM Orders WHERE CONVERT(VARCHAR(10),OrderDate,110) = CONVERT(VARCHAR(10),@Today,110)34 END35 36 END37 38 GO
【转】SQL SERVER 存储过程中变量的作用域
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。