YSQL – Treat NULL as Distinct in Constraints

In a previous YugabyteDB Tip, we explored how constraints like a unique index allow multiple NULL values to be inserted. The tip also demonstrated a workaround to enforce a rule where only one NULL value can be inserted.

PostgreSQL 15 introduced a feature that simplifies enforcing constraints where NULLs are not treated as distinct.

Now that YugabyteDB YSQL is compatible with Postgres 15, the above work around in no longer needed!

Example:

				
					yugabyte=# CREATE TABLE users (id INT PRIMARY KEY, name TEXT, email TEXT);
CREATE TABLE

yugabyte=# CREATE UNIQUE INDEX users_uidx_old ON users (email);
CREATE INDEX

yugabyte=# INSERT INTO users VALUES (1, 'Bob', 'Bob@yugabyte.com');
INSERT 0 1

yugabyte=# INSERT INTO users VALUES (2, 'Bob', NULL);
INSERT 0 1

yugabyte=# INSERT INTO users VALUES (3, 'Bob', NULL);
INSERT 0 1

				
			

The third INSERT statement above does not generate a duplicate key violation and allows the second NULL value to be inserted without error.

To make a unique index treat NULL values as equal, use the NULLS NOT DISTINCT option when creating the index.

				
					yugabyte=# DROP INDEX users_uidx_old;
DROP INDEX

yugabyte=# TRUNCATE TABLE users;
TRUNCATE TABLE

yugabyte=# CREATE UNIQUE INDEX users_uidx_new ON users (email) NULLS NOT DISTINCT;
CREATE INDEX

yugabyte=# INSERT INTO users VALUES (1, 'Bob', 'Bob@yugabyte.com');
INSERT 0 1

yugabyte=# INSERT INTO users VALUES (2, 'Bob', NULL);
INSERT 0 1

yugabyte=# INSERT INTO users VALUES (3, 'Bob', NULL);
ERROR:  duplicate key value violates unique constraint "users_uidx_new"
				
			

As of now, YugabyteDB 2.25.0.0 (preview) is compatible with Postgres 15, and this feature will be available soon in YugabyteDB 2025.1.0.0 (stable). I’ll update this post once 2025.1.0.0 is released!

Have Fun!

The YugabyteDB Team had our annual SKO (Sales Kickoff Meeting) in Santa Cruz, California, last week! And yes, we managed to capture the moment with a group picture—though it might take a few minutes to spot the one person who blinked during the shot!