【问题标题】:select an item with a null comparison选择具有空比较的项目
【发布时间】:2012-08-18 00:53:48
【问题描述】:

我没有使用完整的 DB 抽象库,而是在 psycopg2 中使用如下所示的原始 sql 模板:

 SELECT id FROM table WHERE message = %(message)s ;

检索我的预期结果的理想查询如下所示:

 SELECT id FROM table WHERE message = 'a3cbb207' ;
 SELECT id FROM table WHERE message IS NULL ;

不幸的是...明显的问题是我的 NULL 比较结果如下所示:

 SELECT id FROM table WHERE message = NULL ;

... 这不是正确的比较 - 并且没有给我预期的结果集。

我的实际查询比上图复杂得多 - 所以我不能轻易更改它们。 (这将是正确的解决方案,我同意。我现在正在寻找紧急解决方案)

有谁知道一种解决方法,所以我可以保持相同的单一模板继续运行,直到适当的修复到位?我试图让coalesce 和/或cast 工作,但我的尝试失败了。

【问题讨论】:

    标签: postgresql psycopg2


    【解决方案1】:

    你想要的是IS NOT DISTINCT FROM

    SELECT id FROM table WHERE message IS NOT DISTINCT FROM 'the text';
    
    SELECT id FROM table WHERE message IS NOT DISTINCT FROM NULL;
    

    NULL IS NOT DISTINCT FROM NULLtrue,而不是NULL,所以它类似于=,但具有不同的NULL 比较语义。触发功能很棒。

    AFAIK 不能使用IS DISTINCT FROM 进行索引查找,所以要小心。对 null 和 value 使用单独的测试会更好。

    【讨论】:

    • @muistooshort 感谢您的编辑。我通常记得。真希望 Pg 文档在版本选择器中有一个“当前”,而不仅仅是显式版本,因为确保获得正确的链接会更容易。
    • 我编辑修复了答案中的一个小“反向逻辑错误”。 :-)
    • @kgrittn 谢谢。你相信我从来没有注意到IS NOT DISTINCT FROM 并且一直在写NOT (a IS DISTINCT FROM b) 吗? 掌心
    • 谢谢!这是一个完美的解决方案!
    • 这个答案肯定值得+1
    【解决方案2】:

    您可以尝试如下编写查询子句:

    WHERE message = %(message)s OR ((%message)s IS NULL AND message IS NULL))
    

    有点粗略,但意思是“选择与我的参数匹配的消息,或者如果我的参数为空,则选择所有为空的消息”。它应该可以解决问题。

    【讨论】:

    • 谢谢,已经测试过了,但是另一个使用“非独特形式”的技巧效果更好。
    【解决方案3】:

    不幸的是,NULL 实际上并不等于任何东西(甚至不等于另一个NULL),因为NULL 的值旨在表示一个未知。最好的办法是更改模板以正确处理此问题。

    如果您可以在模板中为左右操作数传入单独的值,那么仍然使用等号的一种方法是:

    SELECT id FROM table WHERE true = (message is null);
    

    【讨论】:

    • 谢谢,已经测试过了,但另一个使用“非独特形式”的技巧效果更好。模板更改将在未来发生。我只需要修复一些正在生产中的东西。
    猜你喜欢
    • 2011-01-24
    • 1970-01-01
    • 2013-11-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-02-02
    • 1970-01-01
    • 2012-09-12
    相关资源
    最近更新 更多