设为首页收藏本站我的广告

运维网

 找回密码
 注册

QQ登录

只需一步,快速开始

扫一扫,访问微社区

搜索
运维网 首页 数据库运维 SQL Server 查看内容

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

2012-4-27 13:37| 发布者: yunweiw.com| 查看: 1445| 评论: 0|原作者: 运维网|来自: 网络

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

  先来看例子。

  [sql] view plaincopy 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)

  [sql] view plaincopy 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 语句中不小心重复定义相同的变量而引起不必要的麻烦,也可以避免像前边的例子中的错误

  [sql] view plaincopy 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

下一篇:常用数据库函数对比

上一篇:关于SQL Server隐式转换


鲜花

握手

雷人

路过

鸡蛋
加入阿里云推荐返利15%

最新评论

QQ|申请友链|sitemap|手机版|小黑屋|Archiver|运维网 ( 京ICP备16008201号  

GMT+8, 2016-12-4 22:28 , Processed in 0.056572 second(s), 30 queries , Xcache On.

Powered by Discuz! X3.2 Licensed

© 2001-2013 Comsenz Inc.

返回顶部