使用可空字段否定SQL WHERE条件

时间:2013-10-05 12:21:32

标签: sql postgresql where nullable

我有一个过滤器,用户可以选择 包含等操作...

  • bubu是xoxo 转换为WHERE lower(bubu) = 'xoxo' SQL WHERE条件。
  • bubu包含xoxo 会转换为WHERE bubu ILIKE '%xoxo%' SQL WHERE条件。

现在我添加了负面变体 - 不是不包含等等。我不想从头开始重写WHERE条件,所以我在前置NOT已经存在的:

  • bubu不是xoxo 转换为WHERE NOT lower(bubu) = 'xoxo' SQL WHERE条件。
  • bubu不包含xoxo 会转换为WHERE NOT bubu ILIKE '%xoxo%' SQL WHERE条件。

然而,有一个问题。如果 bubu 是一个可以为空的字段并且它实际上有NULL,那么负WHERE条件不会选择它,尽管从人的角度来看(而不是SQL),NULL值应该满足 bubu不是xoxo 过滤器。

我通过修改原始的正WHERE条件解决了这个问题:

  • bubu是xoxo 转换为WHERE (lower(bubu) = 'xoxo' AND bubu IS NOT NULL) SQL WHERE条件。

然后,否定产生:

  • bubu不是xoxo 转换为WHERE NOT (lower(bubu) = 'xoxo' AND bubu IS NOT NULL) SQL WHERE条件。

这次正确地拾取了NULL值。同样的问题是包含过滤器。

是否有一个更优雅的解决方案来解决人类如何处理NULL以及SQL如何处理它之间的这种不一致?

我正在使用PostgreSQL 9.2,我不介意拥有特定于此数据库的解决方案。

P.S。

请注意,我希望否定表达式的格式为非正面

2 个答案:

答案 0 :(得分:1)

我认为您应该能够使用COALESCE将NULL转换为空字符串:

-- These skip skips NULLs
lower(coalesce(bubu, '')) = 'xoxo'
coalesce(bubu, '') ilike '%xo%'

-- These will find NULLs
not lower(coalesce(bubu, '')) = 'xoxo'
not coalesce(bubu, '') ilike '%xo%'

当然,如果您正在搜索空字符串,这种技巧会遇到问题,在这种情况下,您需要一个上下文相关的标记值,以便您可以智能地选择一些与您的搜索字词不匹配的内容

演示:http://sqlfiddle.com/#!12/8bbd2/3

答案 1 :(得分:0)

对于=运算符,您可以使用is [not] distinct from构造

WHERE (lower(bubu) is not distinct from 'xoxo')

http://www.postgresql.org/docs/9.2/static/functions-comparison.html