This article is half-done without your Comment! *** Please share your thoughts via Comment ***
PostgreSQL UNIQUE Constraint does not consider a NULL values for uniqueness.
I am surprised when I found few duplicate values in my database where Unique key constraint already defined for that columns.
I know the thumb rule of UNIQUE Constraint is, UNIQUE Key column can be a NULL.
In my Postgres database, I applied Composite Unique Key in multiple columns, and this constraint failed when one of the value is NULL, and another value is NOT NULL.
Below is a full example on this:
Create a sample table with composite Unique Key:
1 2 3 4 5 6 7 8 9 |
CREATE TABLE tbl_TestUniqueNull ( ID INTEGER ,NoA INTEGER ,NoB INTEGER ,NoC INTEGER ,CONSTRAINT pk_tbl_TestUniqueNull_ID PRIMARY KEY(ID) ,CONSTRAINT uk_tbl_TestUniqueNull_NoA_NoB_NoC unique (NoA,NoB,NoC) ); |
Now insert few records with the same combination:
1 2 3 4 5 |
INSERT INTO tbl_TestUniqueNull VALUES (1,1,2,NULL); INSERT INTO tbl_TestUniqueNull VALUES (2,1,2,NULL); INSERT INTO tbl_TestUniqueNull VALUES (3,1,5,NULL); INSERT INTO tbl_TestUniqueNull VALUES (4,3,NULL,1); INSERT INTO tbl_TestUniqueNull VALUES (5,3,NULL,1); |
You can check above result, and we can easily find duplicate combination when one column has a NULL value. Which is wrong and if we have this kind of requirement when we need a composite Unique Key, it fails.
The solution is Unique Index:
In the above situation, we have to use the Unique Index of PostgreSQL.
Create a Unique Index for this example:
1 2 3 |
CREATE UNIQUE INDEX UIdx_NoA_NoB_NoC ON tbl_TestUniqueNull (coalesce(NoA,-1),coalesce(NoB,-1),coalesce(NoC,-1)); |
1 2 3 4 5 6 7 |
ERROR: duplicate key value violates unique constraint "uidx_noa_nob_noc" DETAIL: Key ((COALESCE(noa, (-1))), (COALESCE(nob, (-1))), (COALESCE(noc, (-1))))=(3, -1, 1) already exists. ********** Error ********** ERROR: duplicate key value violates unique constraint "uidx_noa_nob_noc" SQL state: 23505 Detail: Key ((COALESCE(noa, (-1))), (COALESCE(nob, (-1))), (COALESCE(noc, (-1))))=(3, -1, 1) already exists. |