【搬家】【数据库】【语法】SQL 中声明变量使用默认初值存在的隐患
2014-06-18 16:07
423 查看
本文最早于 2013年12月21日于本人个人博客(http://mooowooo.tk)发表,现博客搬家至此,转载请注明出处。
最近在工作中常常遇到数据库 SP 执行完成后总是返回同一个结果的问题,分析后问题出在 SP 中声明变量后未为其赋初值, SP 执行过程中也没有进入到为其赋值的子句,则变量一直保持默认值
Talk is week, let me show you my code.
首先,我在数据库里新建了一张名为
然后,新建一个查询,输入如下 SQL 代码,注意
执行的结果如下图所示:
很显然,因为
执行结果如下图所示:
出现了奇怪的现象,按道理来说,我们修改了条件,
于是我们推测,问题出在
执行结果如下图:
看来问题就出在 NULL 这个特殊的值上。
结果应该很清楚。所以我们知道了,在判断时,对于值为
当然,问题不能一概而论,在此我也只是提出一种问题原因和修补的方法,各位还是要根据自己面临的业务需求灵活选择。程序的设计和编写就是一个
最近在工作中常常遇到数据库 SP 执行完成后总是返回同一个结果的问题,分析后问题出在 SP 中声明变量后未为其赋初值, SP 执行过程中也没有进入到为其赋值的子句,则变量一直保持默认值
NULL,导致最终无法满足任何判断条件而总是执行不正确的结果。
Talk is week, let me show you my code.
首先,我在数据库里新建了一张名为
EMPLOYEE的表,并向其中塞入了一笔数据,如下图
然后,新建一个查询,输入如下 SQL 代码,注意
IF语句中条件的设置。
[code]DECLARE @Result VARCHAR(20) SELECT @Result IF EXISTS ( SELECT 1 FROM EMPLOYEE WHERE NAME='MOOOWOOO' AND ID='000') BEGIN SET @Result = 'Y' END IF @Result = 'Y' BEGIN SELECT 'It is Ok !' END ELSE BEGIN SELECT 'It is Wrong !' END
执行的结果如下图所示:
很显然,因为
EMPLOYEE表中不存在满足这样条件一笔数据,所以
@Result = 'Y'一定不成立,自然的,执行结果会进入
ELSE子句。现在我们来做一点修改:
[code]DECLARE @Result VARCHAR(20) SELECT @Result IF EXISTS ( SELECT 1 FROM EMPLOYEE WHERE NAME='MOOOWOOO' AND ID='000') BEGIN SET @Result = 'Y' END IF @Result <> 'Y' -- 该处条件已经改变 BEGIN SELECT 'It is Ok !' END ELSE BEGIN SELECT 'It is Wrong !' END
执行结果如下图所示:
出现了奇怪的现象,按道理来说,我们修改了条件,
@Result <> 'Y'是一定成立的,理应满足
IF的判断条件,但为何还是执行进入了
ELSE子句呢?此时我们根据图片的来分析,在声明
@Result变量时,我特意留空不为其赋初值,并将其默认值
SELECT出来。大家已经发现,SQL Server 未没有显式赋初值的变量默认赋值为
NULL。
于是我们推测,问题出在
NULL上。稍安勿躁,我们将代码进一步修改成下面的情况来验证我们的猜想。
[code]DECLARE @Result VARCHAR(20) SELECT @Result IF EXISTS ( SELECT 1 FROM EMPLOYEE WHERE NAME='MOOOWOOO' AND ID='000') BEGIN SET @Result = 'Y' END IF @Result = 'Y' BEGIN SELECT 'It is Ok !' END ELSE @Result <> 'Y' BEGIN SELECT 'It is Wrong !' END ELSE @Result IS NULL BEGIN SELECT 'It is NULL !' END ELSE BEGIN SELECT 'What the HELL ???' END
执行结果如下图:
看来问题就出在 NULL 这个特殊的值上。
NULL是一个极为特殊的值,不存在任何实际的值能与之建立逻辑关系,包括
NULL自身。有兴趣又对此问题不太清楚的朋友可以对上面的语句增加如下的一个
ELSE子句进行验证:
[code]ELSE IF @Result = NULL BEGIN SELECT 'It is =NULL !' END
结果应该很清楚。所以我们知道了,在判断时,对于值为
NULL的变量来说,只能使用系统提供的
IS操作符来判断。为了防止出现与我一样的悲剧,建议在编写 SQL 代码时在声明变量的同时就为其显示赋初值,或者对于值可能为 NULL 的情况增加分支判断。对于这个问题,Wikipedia相关条目里有更详尽的分析和说明,各位可以参考。
当然,问题不能一概而论,在此我也只是提出一种问题原因和修补的方法,各位还是要根据自己面临的业务需求灵活选择。程序的设计和编写就是一个
制造错误 发现错误 修改错误 带入新错误的螺旋上升过程,同时也是广大程序员们为其着迷,疯狂,咒骂,悲伤却依旧乐此不疲的原因。
相关文章推荐
- 数据库中存在nchar类型的列时, 使用Linq to sql的问题
- vs2005下使用sql 2000或其他数据库作为membership的默认提供程序
- SQl Server 动态SQL给变量赋值 和OBJECTPROPERTY函数使用及判断表 存储过程 视图等是否存在
- vs2005下使用sql 2000或其他数据库作为membership的默认提供程序
- SQL SERVER STR等函数及语法 与使用实例 与Postgre数据库的函数使用区别
- 动态sql语句基本语法(字段名,表名,数据库名之类作为变量时,必须用动态SQL如ALTER TABLE中使用程序传递的参数)
- 动态sql语句基本语法(字段名,表名,数据库名之类作为变量时,必须用动态SQL如ALTER TABLE中使用程序传递的参数)
- SQL Server 数据库操作总结(sql语法的使用)
- vs2005下使用sql 2000或其他数据库作为membership的默认提供程序
- SQL Server 语法 使用SQL语句创建数据库、表
- 如何监控并找出系统中存在的大量的未使用绑定变量的SQL
- sql语法复习:增删查改,各种数据库对象创建和函数使用
- 动态sql语句基本语法(字段名,表名,数据库名之类作为变量时,必须用动态SQL如ALTER TABLE中使用程序传递的参数)
- SQL Server中变量的声明和使用方法
- 数据库之变量使用语法
- SQLSERVER 表名数据库名作为变量 必须使用动态SQL(源自网络)
- 动态sql语句基本语法(字段名,表名,数据库名之类作为变量时,必须用动态SQL如ALTER TABLE中使用程序传递的参数)
- 数据库-Oracle【Oracle数据库设置默认表空间问题及Oracle,SQL,MySQL的自增变量设置】
- oracle pl/sql之使用游标变量更新数据库
- SQLSERVER 表名数据库名作为变量 必须使用动态SQL(源自网络)