Best way to check for “empty or null value”

和自甴很熟 提交于 2019-11-26 17:01:41
Erwin Brandstetter

The expression stringexpression = '' yields:

TRUE   .. for '' (or for any string consisting of only spaces with the data type char(n))
NULL   .. for NULL
FALSE .. for anything else

So to check for: "stringexpression is either NULL or empty":

(stringexpression = '') IS NOT FALSE

Or the reverse approach (may be easier to read):

(stringexpression <> '') IS NOT TRUE

Works for any character type including the obsolescent char(n) which is hardly ever useful.
The manual about comparison operators.

Or use the expression you already had, just without the trim() which would be useless for char(n)(see below), or it would include strings consisting of only spaces in the test for other character types:

coalesce(stringexpression, '') = ''

But the expressions at the top are faster.

Asserting the opposite: "stringexpression is neither NULL nor empty" is even simpler:

stringexpression <> ''

About char(n)

Do not confuse this data type with other character types like varchar(n), varchar, text or "char" (with quotes), which are all useful data types. This is about the outdated data type with very limited usefulness: char(n), short for: character(n). Also, char and character are short for char(1) / character(1) (same thing).

In char(n) (unlike other string types!) an empty string is not different from any other string consisting of only spaces. All of these are folded to n spaces in char(n) per definition of the type. It follows logically that this works for char(n) as well:

coalesce(stringexpression, '') = ''

Just as much as these (which wouldn't work for other character types):

coalesce(stringexpression, '  ') = '  '
coalesce(stringexpression, '') = '       '

Demo

Empty string equals any string of spaces when cast to char(n):

SELECT ''::char(5) = ''::char(5)     AS eq1
      ,''::char(5) = '  '::char(5)   AS eq2
      ,''::char(5) = '    '::char(5) AS eq3;
eq1 | eq2 | eq3
----+-----+----
t   | t   | t  

Test for "null or empty string" with 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);
 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

Test for "null or empty string" with 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);
 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

dbfiddle here
Old SQL Fiddle

Related:

sam

To check for null and empty:

coalesce(string, '') = ''

To check for null, empty and spaces (trim the string)

coalesce(TRIM(string), '') = ''

If there may be empty trailing spaces, probably there isn't better solution. COALESCE is just for problems like yours.

Something that I saw people using is stringexpression > ''. This may be not the fastest one, but happens to be one of the shortest.

Tried it on MS SQL as well as on PostgreSQL.

Checking for the length of the string also works and is compact:

where length(stringexpression) > 0;

My preffered way to compare nullable fields is: NULLIF(nullablefield, :ParameterValue) IS NULL AND NULLIF(:ParameterValue, nullablefield) IS NULL . This is cumbersome but is of universal use while Coalesce is impossible in some cases.

The second and inverse use of NULLIF is because "NULLIF(nullablefield, :ParameterValue) IS NULL" will always return "true" if the first parameter is null.

If database having large number of records then null check can take more time you can use null check in different ways like : 1) where columnname is null 2) where not exists() 3) WHERE (case when columnname is null then true end)

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!