【问题标题】:Oracle/PL SQL/SQL null comparison on where clause关于 where 子句的 Oracle/PL SQL/SQL 空值比较
【发布时间】:2013-05-29 14:12:42
【问题描述】:

关于处理的问题将在查询中为空值。

例如,我有下表,其中包含以下字段和值

TABLEX
Column1
1        
2        
3      
4        
5      
---------
Column2
null
A
B
C
null

我在一个特定的过程中传递一个变量 Y。程序内部是这样的光标

CURSOR c_results IS
SELECT * FROM TABLEX where column2 = variableY

现在的问题是 variableY 可以是 null、A、B 或 C 如果 variableY 为 null,我想选择 column2 为 null 的所有记录,否则 column2 为 A、B 或 C。

我无法执行上述游标/查询,因为如果 variableY 为 null,它将不起作用,因为比较应该是

CURSOR c_results IS
SELECT * FROM TABLEX where column2 IS NULL

我应该使用什么游标/查询来适应空值或字符串变量。

对不起,如果我的问题有点令人困惑。我不太擅长解释事情。提前致谢。

【问题讨论】:

    标签: sql oracle plsql null


    【解决方案1】:

    Oracle 的 Ask Tom 说:

    where decode( col1, col2, 1, 0 ) = 0  -- finds differences
    

    where decode( col1, col2, 1, 0 ) = 1  -- finds sameness - even if both NULL
    

    Safely Comparing NULL Columns as Equal

    【讨论】:

      【解决方案2】:

      你可以使用DUMP:

      SELECT * 
      FROM TABLEX 
      WHERE DUMP(column2) = DUMP(variableY);
      

      DBFiddle Demo

      警告:这不是 SARG-able 表达式,因此不会使用索引。

      使用这种方法,您无需搜索数据中不存在的值(例如 NVL/COALESCE)。

      【讨论】:

        【解决方案3】:
        WHERE variableY is null or column2 = variableY 
        
        for example:
        create table t_abc (
        id number(19) not null,
        name varchar(20)
        );
        
        insert into t_abc(id, name) values (1, 'name');
        insert into t_abc(id, name) values (2, null);
        commit;
        
        select * from t_abc where null is null or name = null;
        --get all records
        
        select * from t_abc where 'name' is null or name = 'name';
        --get one record with name = 'name'
        

        【讨论】:

        • edit回答并添加解释为什么这应该起作用。
        【解决方案4】:

        以下类似于“顶级”答案,但更简洁:

        WHERE ((column2 = variableY ) or COALESCE( column2, variableY) IS NULL)

        【讨论】:

        • 发帖前请看日期。。也已经分享了答案。
        • 我同意,这更简洁,虽然可能不太清楚
        【解决方案5】:

        你可以使用类似的东西:

        SELECT * FROM TABLEX WHERE COALESCE(column2, '') = COALESCE(variableY, '')
        

        (COALESCE 取第一个非 NULL 值)

        请注意,这仅在您的列内容不能为 ''(空字符串)时才有效。否则此语句将失败,因为 NULL 将匹配 ''(空字符串)。

        (编辑) 你也可以考虑:

        SELECT * FROM TABLEX WHERE COALESCE(column2, 'a string that never occurs') = COALESCE(variableY, 'a string that never occurs')
        

        这将修正''失败假设。

        【讨论】:

        • 在 Oracle NULL NULL 中。所以你的第一个例子是完全错误的。 Demo
        【解决方案6】:

        根据您正在查看的数据,可能不合适,但我见过(并使用过)的一个技巧是比较 NVL(fieldname,somenonexistentvalue)。

        例如,如果 AGE 是可选列,您可以使用:

        if nvl(table1.AGE,-1) = nvl(table2.AGE,-1)
        

        这依赖于你知道永远不会被允许的值。年龄就是一个很好的例子,薪水、序列号和其他不能为负的数字。当然,字符串可能更棘手——你可能会说你永远不会有任何人叫“xyzzymaryhadalittlelamb”或类似的名字,但是当你带着这种假设运行的那一天,你知道他们会雇用那个名字的人!!

        所有所说的:“其中 a = b 或(a 为空,b 为空)”是解决它的传统方法。这是不幸的,因为即使是有经验的程序员有时也会忘记其中的一部分。

        【讨论】:

          【解决方案7】:

          尝试使用ISNULL() 函数。您可以检查变量是否为空,如果是,则设置默认返回值。将 null 转换为 null 是不可能的。记住:空空

          【讨论】:

            【解决方案8】:

            要么根据参数的内容产生不同的 SQL,要么像这样改变你的 SQL:

            WHERE (column2 = variableY) OR (variableY IS NULL AND column2 IS NULL)
            

            【讨论】:

            • 非常感谢拉塞!工作完美!感谢所有帮助过的人。 :)
            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 2022-11-15
            • 1970-01-01
            • 2023-03-31
            • 1970-01-01
            • 2017-01-31
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多