This blog was first authored by Ibrar Ahmed in 2020. We’ve updated it in 2025 for clarity and relevance, reflecting current practices while honoring their original perspective.

Picture this: you’re running what should be a simple query, and PostgreSQL returns completely unexpected results. You double-check your syntax, verify your data, and everything looks correct. The culprit? Those sneaky NULLs hiding in your dataset, behaving nothing like the null values you’re used to in other programming languages.

NULLs in PostgreSQL can trip up even experienced developers. They’re not the same as empty strings or zeros; NULL represents the complete absence of a value. This fundamental difference makes them behave in ways that might surprise you until your queries start returning those head-scratching results.

This post breaks down exactly how PostgreSQL handles NULLs in different contexts and shows you the tools to work with them confidently.

What is NULL?

Most developers encounter NULL early in their careers, but here’s the thing to know: its meaning changes dramatically from language to language. If you’re coming to PostgreSQL from a C or Java background, you might instinctively treat NULL as just another value, and that’s where things go sideways.

Let’s clarify this with two fundamental logic models: bivalent (only TRUE or FALSE) and three-valued (TRUE, FALSE, or UNKNOWN). Many programming languages stick to bivalent logic, but SQL—and therefore PostgreSQL—operates on three-valued logic. This is the key to understanding why NULL behaves the way it does.

How NULL works in different languages

To really grasp PostgreSQL’s approach, let’s see how other languages handle null values.

C/C++

In C and C++, the standard headers define NULL as 0. This means you can compare it using == or != just like any other numeric constant.

A quick test program shows this in action:

The output confirms that in C, NULL is simply 0.

Java

Java takes a different approach, treating null as a special reference value rather than a number. You still use the same equality operators for comparison, but when you print it, you’ll see the literal word “null” (always lowercase in Java).

Understanding NULL in PostgreSQL

PostgreSQL’s NULL means “no value.” It is not 0, an empty string, or a single space, and it won’t cooperate with ordinary equality operators. Instead, PostgreSQL follows three-valued logic: any comparison involving NULL yields UNKNOWN, which in turn behaves like FALSE in WHERE clauses.

Normal numeric comparison:

Normal text comparison:

Compare NULL with NULL:

Inequality doesn’t help:

Math operations are equally fruitless:

 

How to use NULL in PostgreSQL

Since ordinary operators don’t work with NULL, PostgreSQL provides specialized tools designed specifically for these situations.

IS NULL / IS NOT NULL

COALESCE

COALESCE returns the first non-NULL argument from a list. This is incredibly useful for providing fallback values:

NULLIF

NULLIF(a, b) returns NULL if a equals b; otherwise, it returns a. This is handy when you want to convert specific values to NULL:

 

Examples of different NULL uses

Let’s look at some real-world scenarios where NULL handling becomes crucial.

Example 1: Optional middle names

Consider a student table where middle names are optional:

If you try searching for empty strings, you’ll miss the NULL middle name:

Instead, use IS NULL to find records with missing middle names:

NULL is also perfect for data that simply doesn’t apply to certain records. For example, a divorce status for child records:

Example 2: Distinguishing “zero” from “unknown”

This distinction becomes critical when dealing with test scores or measurements:

Here, Bob scored zero (he took the test but failed), while Davis has NULL (perhaps he was absent and hasn’t taken the test yet). This distinction matters for your business logic.

Conclusion

NULL isn’t mysterious once you understand its purpose, but it does require a different mindset. In C, it’s 0; in Java, it’s a non-reference; in PostgreSQL, it represents a third logical state meaning “unknown” or “not applicable.”

The key is treating NULL with the respect it deserves. When you need to work with potentially NULL values, reach for IS NULL, COALESCE, and NULLIF. Try to use regular equality operators or mathematical operations, and you’ll end up with misleading or empty results that will have you scratching your head.

Mastering NULL handling is just one piece of building reliable PostgreSQL applications. As your schema grows and your workload scales, you’ll face new challenges around indexing, high availability, observability, and performance optimization.

That’s where having the right resources makes all the difference. We’ve assembled comprehensive tools, tutorials, and open source expertise to help you keep PostgreSQL reliable, consistent, and future-ready without expensive proprietary add-ons or vendor lock-in.

Check out our PostgreSQL Resource Center to discover how Percona’s fully open source solution gives you the freedom to deploy anywhere, reduce costs, and maintain complete control over your database infrastructure.

Subscribe
Notify of
guest

12 Comments
Oldest
Newest Most Voted
Inline Feedbacks
View all comments

> Especially in databases (PostgreSQL), NULL has some different concepts, so be careful when writing queries involving NULL.

In what databases?

NULL meaning is dictated by SQL standard, and Postgres follows it.

It would be interesting to see if some databases treat it differently compared to the standard.

Federico Razzoli

Good article, but I dissent on one part: I believe that SQL NULL meaning is unclear, and depends on the context.
I explained my point in an article last year:
https://federico-razzoli.com/what-does-null-mean-in-sql

To sum up, my view is that some earlier versions of relational algebra defined two markers (I-marker and A-marker) that defined, respectively, an absent value and an unknown value. SQL standard merged these idea into a single NULL marker in an inconsistent way. The result is that, in practice, sometimes NULLs semantics only make sense if it means absent, sometimes they make sense if it means unknown, and sometimes they don’t make sense in both cases.

Federico Razzoli

@Ibrar Ahmed, on that part I agree. I find most of your article good and useful, and I’m sorry for not stressing this in my first comment. It’s good to explain developers that SQL NULL is not what they could expect if they are familiar with C or Java.

The sentence I disagree with is “In PostgreSQL, NULL means no value”. I agree that this is PostgreSQL intention (because this is what SQL standard says), but in practice all DBMSs I know treat it too inconsistently.

Michael Darrin Chaney, Sr

Every so often a cringy article like this comes out from someone who just found the word NULL in a few different places and went about trying to determine why the same word seemingly means different things.

First, you’re comparing an RDBMS engine (PostgreSQL) to programming languages (C & Java). That doesn’t even make sense. These are not the same thing.

Second, you need to understand it in the historical context. In C, NULL is 0. Why? In Unix systems, the first page of memory (which includes address 0) is typically set as inaccessible to a process. When pointers are initialized to 0, they point to this inaccessible piece of memory. This is one of the best ways to catch an uninitialized pointer, as using it will result in your program crashing immediately. So the uninitialized pointer is a null pointer. We don’t use NULL in other contexts – we just use 0. I wouldn’t put “for (x=NULL; …”. There’s a reason we have this, and it’s not to make typing “0” more difficult.

Third, your database examples are surprisingly good given the rest of this, but you missed one of the qualities of NULL values that is useful. They aren’t used in aggregate functions. For instance, taking the students_mark example, “select count(marks) from students_mark” will give you “2”, and “select average(marks) from students_mark” will give you “4.5”. In a database context, NULL means “missing or unknown”. Unfortunately, those are different concepts and you have to use your programming to make up for it.

Please also see the remarks from Federico Razzoli.

I would also add info about “null” in javascript.

cyberjots

@Ibrar I guess the article is targeting a specific audience that seem to have a niche gap in their knowledge. When looked at from that point of view, a decent write up with good relevant examples.

Also, Federico’s article goes nicely with it. Thanks for the reminder @Federico.

Ibrar Ahmed

Yes, this is for some specified users who comes from different languages and try to learn SQL’s NULL.

Leonardo Erpi

NULL is not always good

Ibrar Ahmed

Yes, we should hope to have data in all column 🙂

Sandor

Nice article. It’s also interesting to note that NULL values are not regarded in unique indices. So, while a duplicate non-NULL value is not allowed in a column that has a unique index on it, more than one NULL value *is* allowed. I’m not sure if this behavior is consistent across all major DMBSs but I suspect so.