• 警惕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 + '--' + @B
    GO
    

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

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

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

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

  • 相关阅读:
    php页面调用微信扫一扫
    mysql大数据表添加字段
    Maven使用本地包的打包和安装(举例微信SDK)
    谈谈统计学正态分布阈值原理在数据分析工作中的运用
    深入剖析 RSA 密钥原理及实践
    Kafka 原理以及分区分配策略剖析
    jenkins+docker实现自动编译、打包、构建镜像、容器部署
    php7安装ldap扩展
    jenkins 简单实现php集成上线部署
    Jenkins 流水线(Pipeline)
  • 原文地址:https://www.cnblogs.com/zuowj/p/4094693.html
Copyright © 2020-2023  润新知