首页 > 代码库 > 警惕SQL语句陷井

警惕SQL语句陷井

以下SQL段,大家认为结果是什么呢?

DECLARE @A VARCHAR(50)	SET @A=‘Zuowenjun.cn‘	SELECT TOP 1 @A=ISNULL(FIELDNAME,‘DEFAULT‘) FROM TABLENAME WHERE 1=2	PRINT @A	GO

可能大家都认为结果显示是:DEFAULT,因为变量@A初始化为:Zuowenjun.cn,在执行SQL查询后,由于条件1=2不成立,所以查询结果FIELDNAME的值应该是NULL,然后再执行ISNULL函数,就会将默认值DEFAULT赋给变量@A,然后最终打印是DEFAULT,但实际执行的结果却并不是这样,而是Zuowenjun.cn,原因是什么呢?经过我的分析,找到了问题的原因,那就是SELECT语句,在找不到的记录的情况下,是不会执行赋值操作的(即:ISNULL(FIELDNAME,‘DEFAULT‘)根本没有执行),所以才会得出该结果,若要解决这个问题,我们可以使用SET关键字给变理赋值,如下改良过后SQL段:

DECLARE @A VARCHAR(50)	SET @A=‘Zuowenjun.cn‘	SET @A=ISNULL((SELECT TOP 1 FIELDNAME FROM TABLENAME WHERE 1=2),‘DEFAULT‘)	PRINT @A	GO

这样执行的结果就是DEFAULT,但这样存在局限性,因为SET只支持单个变量赋值,那同时给多个变量赋值则无法适用,所以如果需要给多个变量同时赋值的情况,我们可以采用如下方法,虽然有点复杂,但不影响执行效率:

DECLARE @A VARCHAR(50),@B VARCHAR(50)SET @A=‘Zuowenjun.cn‘SET @B=‘XXXX‘SELECT @A=ISNULL(FIELDNAME1,‘DEFAULT1‘),@B=ISNULL(FIELDNAME2,‘DEFAULT2‘)FROM (SELECT 1 AS F1)  T1 left join(SELECT TOP 1 FIELDNAME1,FIELDNAME2,1 AS F1 FROM TABLENAME  WHERE 1=2) T2 on T1.F1=T2.F1 PRINT @A + ‘--‘ + @BGO

说一下原理,因为(SELECT 1 AS F1)始终返回一条记录1,然后用这个表T1左连接我们要查询的SQL语句 T2,1 AS F1这个是必需的,因为关联需要用到,根据左连接的原则,左表不论右边是符合关联条件,都会返回记录,所以最外层的SELECT是一定有值,FIELDNAME1与FIELDNAME2这时都是NULL,执行ISNULL函数自然就得到了默认值。

当然以上情形是用在SQL查询语句可能存在不符合查询条件的情况,若确定能返回值,则没有必要这样做,或者即使存在不符合的情况,也可以通过后续逻辑判断来重新给变量赋值达到相同的效果,只是要写的语句就多些。

该篇文章为作者本人原创,文章内容仅表达个人意见或想法,仅供参考,若大家对此有不同的意见可参与评论,谢谢!

更多IT相关的文章,欢迎光临我的个人网站:http://www.zuowenjun.cn/

警惕SQL语句陷井