zoukankan      html  css  js  c++  java
  • 警惕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/

  • 相关阅读:
    2020下第八周总结
    《程序员的自我修养》——阅读感悟1
    2020下第七周总结
    【基础组件11】hdfs与hbase
    【基础组件10】hadoop拓展(三)NameNode工作机制
    【基础组件9】hadoop入门(二)启动节点、集群、hdfs查看文件系统、清数据
    【基础组件8】hadoop入门(一)集群搭建/ HDFS-HA高可用搭建
    【基础组件7】flink入门(一)集群搭建、实时数据处理
    【基础组件6】kafkamanager安装部署+详细参数讲解+使用教程
    【基础组件5】kafka入门(一)集群搭建+常用命令+基本原理+存储分析
  • 原文地址:https://www.cnblogs.com/zuowj/p/4094693.html
Copyright © 2011-2022 走看看