postgres:如何保护条件表达式不受空值的影响

时间:2017-08-04 16:51:01

标签: sql postgresql short-circuiting

在使用Postgresql多年之后,我仍然不知道是否存在关于如何保护条件表达式免受变量空值的最佳实践,因为SQL查询规划者具有应用或忽略的完全权限最常用的习惯用语来保护空值:" var为null或var = 0"。

据称,当......结束时使用'语法解决了任何歧义,但也降低了可维护性,因为它用大量单词模糊了一个简单的过程。

提前谢谢。

2 个答案:

答案 0 :(得分:1)

我认为你比较SQL和Java(或C,C ++或任何处理引用指针的语言)会产生误解。

使用SQL时,

在SQL中,您没有(隐藏)指向应该针对NULL测试的对象的指针(或引用),否则它们不能被解除引用。在SQL中,每个表达式都会生成某个类型的某个。此值可以是NULL(也称为NULL)。

如果您的UNKNOWNvar,那么NULL将评估为var = 0未知 = 0会返回 unknown )。然后NULL未知 未知)将评估为var IS NULL。并且,根据三值逻辑,TRUE评估为TRUE or UNKNOWN。无论哪个是评估顺序,结果总是一样的。

您可以通过评估来检查:

TRUE

返回

null_equals_zero | null_is_null | true_or_null | your_case_when_var_is_null | the_same_reordered
:--------------- | :----------- | :----------- | :------------------------- | :-----------------
null             | t            | t            | t                          | t                 

dbfiddle here

给定SELECT /* var */ NULL = 0 as null_equals_zero, /* var */ NULL IS NULL as null_is_null, TRUE or NULL AS true_or_null, (NULL = 0) OR (NULL IS NULL) AS your_case_when_var_is_null, (NULL IS NULL) OR (NULL = 0) AS the_same_reordered ; = 0,NULL和1(<> 0);你会得到:

var
 var | var_equals_zero_or_var_is_null | var_is_null_or_var_equals_zero | the_same_with_protection
---: | :----------------------------- | :----------------------------- | :-----------------------
   0 | t                              | t                              | t                       
null | t                              | t                              | t                       
   1 | f                              | f                              | f                       

dbfiddle here

这些是使用three-valued logic的不同运算符(NOT,AND,OR,IS NULL,XOR,IMPLIES)的基本真值表,并使用SQL检查:

WITH vals(var) AS
(
    VALUES
    (0),
    (NULL),
    (1)
)
SELECT
    var,
    var = 0 OR var IS NULL  AS var_equals_zero_or_var_is_null,
    var IS NULL OR var = 0  AS var_is_null_or_var_equals_zero,
    CASE WHEN var IS NULL then true
         WHEN var = 0 then true
         ELSE false
    END                     AS the_same_with_protection
FROM
    vals ;

这是真相表:

a    | b    | a_equals_null | a_is_null | a_or_b | a_and_b | not_a | a_xor_b | a_implies_b
:--- | :--- | :------------ | :-------- | :----- | :------ | :---- | :------ | :----------
null | null | null          | t         | null   | null    | null  | null    | null       
null | f    | null          | t         | null   | f       | null  | null    | null       
null | t    | null          | t         | t      | null    | null  | null    | t          
f    | null | null          | f         | null   | f       | t     | null    | t          
f    | f    | null          | f         | f      | f       | t     | f       | t          
f    | t    | null          | f         | t      | f       | t     | t       | t          
t    | null | null          | f         | t      | null    | f     | null    | null       
t    | f    | null          | f         | t      | f       | f     | t       | f          
t    | t    | null          | f         | t      | t       | f     | f       | t          

dbfiddle here

答案 1 :(得分:0)

我似乎只问了一个永远存在的问题。因此,根据SQL逻辑表达式中的NULL传播问题,以及sql优化器不遵守短路结构以及不断发展SQL标准的危险,让我分享到目前为止我发现的内容:

  1. 阅读维基百科关于SQL NULL PROPAGATION
  2. 的文章
  3. 在任何具有可能空值的列名周围使用coalesce(),参与sql语句中的任何计算(感谢Igor)。
  4. 同样使用' [不]与'而不是' ='或'<>'