• 结合 Mybatis,探讨 Oracle 中 in 与 not in 的陷阱


    一、Oracle 中的 in 与 not in

    1. 正常情况下的使用

    查询语句使用 in 和 not in 的例子

    --表:T_USER,USER_ID 有 1,2,3,4,5,6
    --查询 userId 中包含1,2,3的数据
    --查询结果:1,2,3
    SELECT * FROM T_USER T WHERE T.USER_ID IN (1, 2, 3);
    
    --查询 userId 中不包含1,2,3的数据
    --查询结果:4,5,6
    SELECT * FROM T_USER T WHERE T.USER_ID NOT IN (1, 2, 3);
    

    2. 数据为空时的使用

    数据为空时,是最容易产生理解错误和查询报错。

    数据为“空”表现为,没有数据或者数据为 null 。如以下两种情景:

    • 数据为空,例如
    SELECT * FROM T_USER T WHERE T.USER_ID IN ();
    

    这时候查询语句会报错,“缺失表达式”。

    • 数据为 null,例如
    SELECT * FROM T_USER T WHERE T.USER_ID IN (NULL);
    

    这时候查询结果为空,即没有任何数据。

    而此种情况下容易产生理解错误的是以下两个查询语句:

    SELECT * FROM T_USER T WHERE T.USER_ID IN (NULL);
    

    SELECT * FROM T_USER T WHERE T.USER_ID NOT IN (NULL);
    

    很多人以为这两个查询语句的查询结果应该是相反的,即 IN (NULL) 查不出数据,而 NOT IN (NULL) 查出所有数据,或者反过来。

    但实际的查询结果是,两个语句查询结果都为空,即都没有数据。

    二、结合 Mybatis,探讨 Oracle 中 in 与 not in 的陷阱

    1. 常用场景:

    在 Mybatis 中使用 in 或者 not in 的方式如下:

    <if test="null != list and list.size > 0 ">
        AND T.USER_ID IN
        <foreach collection="list" item="userID" open="(" separator="," close=")">
            #{userID}
        </foreach>
    </if>
    

    这种方式可以有效避免因为出现 IN ( ) 而导致的缺失表达式异常。

    但是这个表达式所使用的场景是,有 userID 集合时,查询出集合中 userID 数据;没有 userID 集合时,查询出所有 userID 的数据。

    2. 特殊场景:当没有 userID 集合时,不查任何数据

    偶尔会出现这样的使用场景,当没有 userID 集合时,不查任何数据。

    这时候就有人会把 if 条件去掉,即采用如下的查询方式

    AND T.USER_ID IN
    <foreach collection="list" item="userID" open="(" separator="," close=")">
        #{userID}
    </foreach>
    

    很容易理解为什么有人会这么写。list 有值时,in 就有数据,查询也就有数据;list 为空时,in 就没有数据,查询也就得不到数据。

    理想很丰富,现实很骨感。

    如果你这么写的时候,你们当list为空时,就会出现如下的查询语句

    AND T.USER_ID IN
    

    直接导致缺失表达式异常。

    我的一个解决办法是,在 list 中增加一个数据库中没有的 userID,例如 userID = 0 的数据

    那么当你需要的 list 为空时,list 中仍然保留有 0 这个值。于是,当你查询时会出现如下语句

    AND T.USER_ID IN (0)
    
  • 相关阅读:
    MOSS 2010 修改管理员密码 欧阳锋
    MOSS2010 中“找不到位于xxxx的web应用程序”的解决办法 欧阳锋
    MSSQL 2008 无法修改表问题的解决 欧阳锋
    不是每个在你身上拉屎的都是你的敌人 欧阳锋
    笑一笑 欧阳锋
    隐藏MOSS2010 左边的导航 欧阳锋
    爱情与婚姻的区别 欧阳锋
    两年后,我们怎么办
    C#控件的闪烁问题解决方法总结
    Linux内核编译配置过程
  • 原文地址:https://www.cnblogs.com/zhenggc/p/13655495.html
Copyright © 2020-2023  润新知