检查"空值或空值"的最佳方法

And*_*rus 149 sql database postgresql null coalesce

在Postgres sql语句中检查value是null还是空字符串的最佳方法是什么?

值可以是长表达式,因此最好只检查一次.

目前我正在使用:

coalesce( trim(stringexpression),'')=''
Run Code Online (Sandbox Code Playgroud)

但它看起来有点难看.

stringexpression可以是char(n)包含char(n)具有尾随空格的列的列或表达式.

最好的方法是什么?

Erw*_*ter 250

表达式stringexpression = ''产生:

TRUE   .. for ''(或任何只包含数据类型空格的字符串char(n))
NULL   .. for NULL
FALSE ... for other else

所以要检查:" stringexpression是NULL还是空":

(stringexpression = '') IS NOT FALSE
Run Code Online (Sandbox Code Playgroud)

或者相反的方法(可能更容易阅读):

(stringexpression <> '') IS NOT TRUE
Run Code Online (Sandbox Code Playgroud)

适用于任何字符类型,包括char(n)几乎没有用的过时.
有关比较运算符的手册.

或者使用你已经拥有的表达式,只是没有trim()它将是无用的char(n)(见下文),或者它将包括在其他字符类型的测试中仅包含空格的字符串:

coalesce(stringexpression, '') = ''
Run Code Online (Sandbox Code Playgroud)

但顶部的表达式更快.

断言相反:" stringexpression既不是NULL也不是空"甚至更简单:

stringexpression <> ''
Run Code Online (Sandbox Code Playgroud)

关于 char(n)

不要混淆与其他字符类型这样的数据类型varchar(n),varchar,text"char"(带引号),这些都是有用的数据类型.这是关于过时的数据类型,其用途非常有限:char(n)简称:character(n).此外,char还是/ (同样的事情)的character缩写.char(1)character(1)

char(n)(与其他字符串类型不同!)中,空字符串与仅由空格组成的任何其他字符串没有区别.根据类型的定义,所有这些都被折叠到n个空格char(n).从逻辑上讲,这也适用于char(n):

coalesce(stringexpression, '') = ''
Run Code Online (Sandbox Code Playgroud)

和这些一样多(这对其他字符类型不起作用):

coalesce(stringexpression, '  ') = '  '
coalesce(stringexpression, '') = '       '
Run Code Online (Sandbox Code Playgroud)

演示

当转换为char(n):时,空字符串等于任何空格字符串:

SELECT ''::char(5) = ''::char(5)     AS eq1
      ,''::char(5) = '  '::char(5)   AS eq2
      ,''::char(5) = '    '::char(5) AS eq3;
Run Code Online (Sandbox Code Playgroud)
eq1 | eq2 | eq3
----+-----+----
t   | t   | t  
Run Code Online (Sandbox Code Playgroud)

使用以下方法测试"null或空字符串" char(n):

SELECT stringexpression 
      ,stringexpression = ''                    AS simple_test
      ,(stringexpression = '')  IS NOT FALSE    AS test1
      ,(stringexpression <> '') IS NOT TRUE     AS test2
      ,coalesce(stringexpression, '') = ''      AS test_coalesce1
      ,coalesce(stringexpression, '  ') = '  '  AS test_coalesce2
      ,coalesce(stringexpression, '') = '  '    AS test_coalesce3
FROM  (
   VALUES
     ('foo'::char(5))
   , ('')
   , (NULL)
   , ('   ')                -- not different from '' in char(n)
   ) sub(stringexpression);
Run Code Online (Sandbox Code Playgroud)
 stringexpression | simple_test | test1 | test2 | test_coalesce1 | test_coalesce2 | test_coalesce3
------------------+-------------+-------+-------+----------------+----------------+----------------
 foo              | f           | f     | f     | f              | f              | f
                  | t           | t     | t     | t              | t              | t
                  |             | t     | t     | t              | t              | t
                  | t           | t     | t     | t              | t              | t
Run Code Online (Sandbox Code Playgroud)

用"."测试"null或空字符串" text

SELECT stringexpression 
      ,stringexpression = ''                    AS simple_test
      ,(stringexpression = '')  IS NOT FALSE    AS test1
      ,(stringexpression <> '') IS NOT TRUE     AS test2
      ,coalesce(stringexpression, '') = ''      AS test_coalesce1
      ,coalesce(stringexpression, '  ') = '  '  AS test_coalesce2
      ,coalesce(stringexpression, '') = '  '    AS test_coalesce3
FROM  (
   VALUES
     ('foo'::text)
   , ('')
   , (NULL)
   , ('   ')                -- different from '' in a sane character type like text
   ) sub(stringexpression);
Run Code Online (Sandbox Code Playgroud)
 stringexpression | simple_test | test1 | test2 | test_coalesce1 | test_coalesce2 | test_coalesce3
------------------+-------------+-------+-------+----------------+----------------+----------------
 foo              | f           | f     | f     | f              | f              | f
                  | t           | t     | t     | t              | f              | f
                  |             | t     | t     | t              | t              | f
                  | f           | f     | f     | f              | f              | f
Run Code Online (Sandbox Code Playgroud)

dbfiddle 这里
老SQL小提琴

有关:

  • `select coalesce('','')=''`返回false.所以TRIM()是必需的 (3认同)
  • @a_horse_with_no_name:OP询问`检查value是null还是空字符串`的最佳方法.`trim()`调用(相对)昂贵 - 而且没有必要.我添加了更多关于`char(n)`和"empty string"的内容. (2认同)
  • 使用“(stringexpression = '') IS NOT FALSE”是一个糟糕的建议,因为可读性很差。当 stringexpression 为 NULL 时会发生什么,读者可能会感到困惑。使用合并是一个更好的主意。可读性**重要**。如果有人误解您的代码,可能会导致错误。许多代码是由具有不同经验的多个人多年来阅读的。 (2认同)

小智 35

要检查null和empty:

coalesce(string, '') = ''
Run Code Online (Sandbox Code Playgroud)

检查null,空和空格(修剪字符串)

coalesce(TRIM(string), '') = ''
Run Code Online (Sandbox Code Playgroud)

  • 我喜欢这个答案的简单/清晰。 (6认同)

小智 6

另一种方式是

nullif(trim(stringExpression),'') is not null
Run Code Online (Sandbox Code Playgroud)

  • 最佳答案 恕我直言 (2认同)

ygl*_*odt 5

检查字符串的长度也可以并且很紧凑:

where length(stringexpression) > 0;
Run Code Online (Sandbox Code Playgroud)

  • 你检查过这个 NULL 的情况吗? (2认同)
  • 是的,我做到了。它不返回空字符串字段或空字符串字段。 (2认同)

小智 5

许多答案是最短的方法,如果列有很多空值,则不一定是最好的方法。分解检查允许优化器更快地评估检查,因为它不必在其他条件下工作。

(stringexpression IS NOT NULL AND trim(stringexpression) != '')
Run Code Online (Sandbox Code Playgroud)

由于第一个条件为假,因此不需要评估字符串比较。