SQL SERVER 存储过程中变量的作用域

今天遇到一个很有趣的事情,以前没有注意过,所以记下来。

先来看例子。

 

SET ANSI_NULLS ON

GO

SET QUOTED_IDENTIFIER ON

GO

 

CREATE PROCEDURE GetOrderBeforeDays

    @BeforDays INT

AS

BEGIN

    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)
    END

END

GO


 

这个存储过程创建时不会有什么问题,但实际执行时是不正确的,当参数大于0时并不能获取当天的数据。仔细看会发现@Today变量的定义在第一个IF语句中,但是在ELSE语句中竟然也可以使用,这与C#中的用法有所不同。

 

原来SQL SERVER中,声明变量的地方开始到声明变量的批处理或存储过程的结尾,因此在ELSE语句中也可以访问到IF语句中定义的变量。

 

但这会引起一些不必要的错误。如前边的例子中,虽然在ELSE语句中可以访问到定义的变量,但是并没有被赋值,所以执行时是查不到当天的定单的。

 

所以建议尽可能的把所有的变量和初始化都放在存储过程的最开始,一眼就可以看出定义了哪些变量,并赋了什么值。这样一来可以防止在大量的IF ELSE 语句中不小心重复定义相同的变量而引起不必要的麻烦,也可以避免像前边的例子中的错误

 

SET ANSI_NULLS ON

GO

SET QUOTED_IDENTIFIER ON

GO

 

CREATE PROCEDURE GetOrderBeforeDays

    @BeforDays INT

AS

BEGIN

    DECLARE @Today DATETIME

    SET @Today = GETDATE()

    DECLARE @Date DATETIME

    SET @Date = DATEADD(DAY,@BeforDays,@Today)

    IF @BeforDays < 0
    BEGIN
	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)
    END

END

GO


 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值