307

What is best way to check if value is null or empty string in Postgres sql statements?

Value can be long expression so it is preferable that it is written only once in check.

Currently I'm using:

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

But it looks a bit ugly.

stringexpression may be char(n) column or expression containing char(n) columns with trailing spaces.

What is best way?

Erwin Brandstetter
  • 605,456
  • 145
  • 1,078
  • 1,228
Andrus
  • 26,339
  • 60
  • 204
  • 378

11 Answers11

487

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 char(n). The manual about comparison operators.

Or use your original expression without trim(), which is costly noise for char(n) (see below), or incorrect for other character types: strings consisting of only spaces would pass as empty string.

coalesce(stringexpression, '') = ''

But the expressions at the top are faster.

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

stringexpression <> ''

About char(n)

This is about the data type char(n), short for: character(n). (char / character are short for char(1) / character(1).) Its use is discouraged in Postgres:

In most situations text or character varying should be used instead.

Do not confuse char(n) with other, useful, character types varchar(n), varchar, text or "char" (with double-quotes).

In char(n) 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 the above expressions work for char(n) as well - 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;

Result:

 eq1 | eq2 | eq3
 ----+-----+----
 t   | t   | t

Test for "null or empty string" with char(n):

SELECT stringexpression 
     , stringexpression = ''                   AS base_test
     , (stringexpression = '')  IS NOT FALSE   AS test1
     , (stringexpression <> '') IS NOT TRUE    AS test2
     , coalesce(stringexpression, '') = ''     AS coalesce1
     , coalesce(stringexpression, '  ') = '  ' AS coalesce2
     , coalesce(stringexpression, '') = '  '   AS coalesce3
FROM  (
   VALUES
     ('foo'::char(5))
   , ('')
   , ('   ')                -- not different from '' in char(n)
   , (null)
   ) sub(stringexpression);

Result:

 stringexpression | base_test | test1 | test2 | coalesce1 | coalesce2 | coalesce3 
------------------+-----------+-------+-------+-----------+-----------+-----------
 foo              | f         | f     | f     | f         | f         | f
                  | t         | t     | t     | t         | t         | t
                  | t         | t     | t     | t         | t         | t
 null             | null      | t     | t     | t         | t         | t

Test for "null or empty string" with text:

SELECT stringexpression 
     , stringexpression = ''                   AS base_test
     , (stringexpression = '')  IS NOT FALSE   AS test1
     , (stringexpression <> '') IS NOT TRUE    AS test2
     , coalesce(stringexpression, '') = ''     AS coalesce1
     , coalesce(stringexpression, '  ') = '  ' AS coalesce2
     , coalesce(stringexpression, '') = '  '   AS coalesce3
FROM  (
   VALUES
     ('foo'::text)
   , ('')
   , ('   ')                -- different from '' in sane character types
   , (null)
   ) sub(stringexpression);

Result:

 stringexpression | base_test | test1 | test2 | coalesce1 | coalesce2 | coalesce3 
------------------+-----------+-------+-------+-----------+-----------+-----------
 foo              | f         | f     | f     | f         | f         | f
                  | t         | t     | t     | t         | f         | f
                  | f         | f     | f     | f         | f         | f
 null             | null      | t     | t     | t         | t         | f

db<>fiddle here
Old sqlfiddle

Related:

Erwin Brandstetter
  • 605,456
  • 145
  • 1,078
  • 1,228
  • Maybe I'm missing something, but it doesn't check for leading or trailing whitespace. –  May 20 '14 at 19:12
  • 2
    @a_horse_with_no_name: OP asks for the `best way to check if value is null or empty string`. The `trim()` call is (comparatively) expensive - and just not necessary. I added more about `char(n)` and "empty string". – Erwin Brandstetter May 20 '14 at 19:42
  • 1
    You wrote that any string expression containing only spaces is equal to `''` . Can I remove trim and use `coalesce(stringexpression,'')=''` to check. This looks more readable to me compared to your answer. – Andrus May 21 '14 at 14:08
  • 1
    @Andrus: Yes, you can. I added that and some more to the answer. – Erwin Brandstetter May 21 '14 at 14:54
  • 3
    `select coalesce(' ', '') = ''` returns false. So TRIM() is required – Andrus May 21 '14 at 18:17
  • 1
    But `coalesce(' '::char(5), '') = ''` does not. I would use one of the top two expressions in any case, which work for any character type and are fastest and cleanest. – Erwin Brandstetter May 21 '14 at 18:58
  • The fastest queries you mention are not working on Oracle. This query will work on oracle and postgres : WHERE NOT(stringexpression <> ''); – Woody Sep 06 '17 at 14:10
  • @Woody: It will return NULL for NULL input. That's *not* what the question is asking for. This answer is for Postgres, not Oracle, where NULL and the empty string are considered the same - in violation of the SQL standard. – Erwin Brandstetter Sep 06 '17 at 14:19
  • You are right, coalesce will do the job for Oracle, thanks – Woody Sep 06 '17 at 14:32
  • The expression "Or the reverse approach (may be easier to read): (stringexpression <> '') IS NOT TRUE" is not true. – ayhan Jun 30 '21 at 09:14
  • @ayhan: What's not true? – Erwin Brandstetter Jun 30 '21 at 10:50
  • Oh, I misunderstood that line. By saying "reverse approach", I thought "stringexpression is neither NULL nor empty" is meant, but I see that another way of expressing "stringexpression is either NULL or empty" is shown at that line. So that expression is correct. Sorry. – ayhan Jun 30 '21 at 11:36
  • 2
    Using `(stringexpression = '') IS NOT FALSE` is a bad advice because of poor readablity. It may be confusing for the reader as to what happens when stringexpression is NULL. Using coalesce fot this is a much better idea. Readability is **important**. If someone misunderstands your code it may result in a bug. A lot of code is read by multiple people, with varying experience, over multiple years. – godfryd Mar 18 '22 at 13:51
  • 1
    Google brought me here even though I was looking for the opposite case: `Not null Nor empty`... I wonder if you can add it as an fyi to complete the very nice answer... *EDIT*: well, it should be `(stringexpression = '') IS FALSE` xD – Enissay Jun 10 '22 at 00:48
  • 1
    @Enissay: Simply `stringexpression <> ''` for *"Not null Nor empty"*. That's already added in above. – Erwin Brandstetter Jun 10 '22 at 01:16
  • Using "Postgres 11" and only original version with "coalesce" and "trim" (from question) works for space-filled strings for me: `coalesce( trim(stringexpression),'')=''` – Rib47 Jun 21 '22 at 08:00
110

To check for null and empty:

coalesce(string, '') = ''

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

coalesce(TRIM(string), '') = ''
Amgad Fahmi
  • 4,349
  • 3
  • 19
  • 18
  • btw, `coalesce(a, ...b)` returns the first non-null value (https://www.postgresql.org/docs/8.1/functions-conditional.html) – bendytree Jun 21 '21 at 20:46
36

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

where length(stringexpression) > 0;
yglodt
  • 13,807
  • 14
  • 91
  • 127
12

A lot of the answers are the shortest way, not the necessarily the best way if the column has lots of nulls. Breaking the checks up allows the optimizer to evaluate the check faster as it doesn't have to do work on the other condition.

(stringexpression IS NOT NULL AND trim(stringexpression) != '')

The string comparison doesn't need to be evaluated since the first condition is false.

John VE
  • 131
  • 1
  • 3
11

another way is

nullif(trim(stringExpression),'') is not null
Mowazzem Hosen
  • 457
  • 4
  • 10
2

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

Świstak35
  • 350
  • 2
  • 12
2

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.

TarasB
  • 2,407
  • 1
  • 24
  • 32
1

found this post looking for a solution to 'don't show me data that is '' (blank or single space char) or null'. in my case, we only want to show the user records with these values populated. i hope this response helps another looking for the same. the answers above didn't work in my case.

our app is running rails with postgres. looking at how rails builds the query for .where.not(company_website: [nil, '']) in our app, which works just fine, i can see the resulting sql statement in console.

WHERE NOT ((contacts.company_website = '' OR contacts.company_website IS NULL))

i added this bit and it works as intended.

1

I like answer by yglodt, but calculating exact length may be expensive for big sets and big strings, so I go with:

coalesce(trim('a') > '','f')
noonex
  • 1,975
  • 1
  • 16
  • 18
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.

0

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)

Ammy
  • 369
  • 2
  • 8