In SQL null is not equal ( = ) to anything—not even to another null . According to the three-valued logic of SQL, the result of null = null is not true but unknown. SQL has the is [not] null predicate to test if a particular value is null .

With is [not] distinct from SQL also provides a comparison operator that treats two null values as the same.

<expression> IS NOT DISTINCT FROM <expression>

Note that you have to use the negated form with not to arrive at similar logic to the equals ( = ) operator.

The following truth table highlights the differences between the equals sign ( = ) and is not distinct from .

A B A = B A IS NOT DISTINCT FROM B 0 0 true true 0 1 false false 0 null unknown false null null unknown true

The result with equals ( = ) is unknown if one operator is null . The is not distinct from comparison is true if both values are null or false if only one is null .

Conforming Alternatives

Note Although there are standard alternatives to is not distinct from , using a proprietary alternative is often the better choice.

Due to SQL’s three-valued logic, a fully equivalent substitute for A is not distinct from B that works in all SQL databases is surprisingly complex—even when we limit the requirement to cases where evaluating the expressions A and B is deterministic and has no side-effects.

CASE WHEN (a = b) or (a IS NULL AND b IS NULL) THEN 0 ELSE 1 END = 0

The result of the expression in the when clause is true if both arguments are equal or both are null . If only one argument is null the result is unknown, not false. This is often not a problem because SQL generally treats unknown like false when making binary decisions such as accepting or rejecting a row for a where clause.

To get the fully equivalent functionality of is not distinct from —i.e. either true or false but never unknown—the case expression reduces the three-valued result into a two a two-valued one. In some databases is not false can be used instead of the case expression. This technique is explained in “Binary Decisions Based on Three-Valued Results”.

On my Own Behalf I make my living from training, other SQL related services and selling my book. Learn more at https://winand.at/.

Another option is to use table operators, which use distinct comparisons internally. The following snippet uses intersect to determine a common subset. The two compared sets are just one value each (one row with one column). If it is twice the same value the common subset will be that value. Otherwise the common subset is empty. This logic can be easily tested in the where clause with an exists predicate:

EXISTS (VALUES (A) INTERSECT VALUES (B) )

This has the advantage that it does not repeat any expressions. Unfortunately, it doesn’t work on all databases due to the use of the values clause. A select from a one-row dummy table can be used to get a conforming and widely supported solution.

Compatibility

The is [not] distinct from predicate was introduced in two steps: SQL:1999 added T151, “DISTINCT predicate”. The optional negation with not was added by SQL:2003 as feature T152, “DISTINCT predicate with negation”.

Proprietary Alternatives

Most database that do not offer is not distinct from offer a proprietary alternative that is more convenient than the conforming alternative described above. The following proprietary features are fully compatible—i.e. they have a two-valued result and never return unknown.

Exists , select without from , intersect

The standard solution using exists , values , and intersect can easily be modified to work on more databases by using select without from instead of the values clause:

EXISTS (SELECT c1 INTERSECT SELECT c2 )

decode — Db2, Oracle, H2

Db2, Oracle database, and H2 have the proprietary function decode that happens to use is not distinct from semantics internally. The following example has the same effect as A is not distinct from B :

DECODE(A, B, 0, 1) = 0

is — SQLite, H2

The is operator of SQLite (documentation) and H2 (documentation) is able to compare two expressions (not just is [not] null ), and it has the same semantics as is not distinct from .

<=> — MySQL, MariaDB

MySQL offers the proprietary <=> comparison operator that works like is not distinct from .

ANSI_NULLS — SQL Server

SQL Server’s deprecated ANSI_NULLS setting makes some equals comparison ( = ) act as though it was a is not distinct from comparison.