PostgreSQL multi-column unique constraint and NULL valuesCustom unique column constraint, only enforced if...

What is an explicit bijection in combinatorics?

UK visa start date and Flight Depature Time

How to transport 10,000 terrestrial trolls across ocean fast?

How to Build a List from Separate Lists

Are there any rules for handling distractions whilst performing skill checks?

SQL Server Service does not start automatically after system restart

Short story about a man betting a group he could tell a story, and one of them would disappear and the others would not notice

Sets which are both Sum-free and Product-free.

How to purchase a drop bar bike that will be converted to flat bar?

Integral problem. Unsure of the approach.

typeof generic and casted type

Are all power cords made equal?

Is there a name for this series?

Why is it that Bernie Sanders always called a "socialist"?

What does an unprocessed RAW file look like?

How can I differentiate duration vs starting time

What really causes series inductance of capacitors?

Does しかたない imply disappointment?

Can a Way of Shadow Monk use Shadow Step to teleport to a dark ceiling and then body slam another creature?

Is there any danger of my neighbor having my wife's signature?

Can I legally make a website about boycotting a certain company?

How can I give a Ranger advantage on a check due to Favored Enemy without spoiling the story for the player?

How can I handle players killing my NPC outside of combat?

Is there a configuration of the 8-puzzle where locking a tile makes it harder?



PostgreSQL multi-column unique constraint and NULL values


Custom unique column constraint, only enforced if one column has a specific valuePostgreSQL UPSERT issue with NULL valuesTwo-column foreign key constraint only when third column is NOT NULLIs it reasonable to mark all columns but one as primary key?Foreign Key NULL vs Foreign Key to an empty stringUnique constraint to enforce max one null per itemComplex constraint across all data in a tableCreating a partial unique constraint for MySQLRestrict two specific column values from existing at the same timeCan column uniqueness be commutative?Any way around unique index 16 column maxunique key violation occuring on a unique value combinationUnique constraint on multiple nullable columns Sql Serverduplicate key violates unique constraint when using multi-threadingSQL Server unique index, per subset of data, based on values of another columnEnforce uniqueness across optional attributes for an entityPostgreSQL UPSERT issue with NULL valuesSQL Insert multiple values with UNIQUE constraintInserting two NULLs values into an UNIQUE column in SQLiteMySQL Varchar Primary Key With Not Null Constraint Accepting Nulls













85















I have a table like the following:



create table my_table (
id int8 not null,
id_A int8 not null,
id_B int8 not null,
id_C int8 null,
constraint pk_my_table primary key (id),
constraint u_constrainte unique (id_A, id_B, id_C)
);


And I want (id_A, id_B, id_C) to be distinct in any situation. So the following two inserts must result in an error:



INSERT INTO my_table VALUES (1, 1, 2, NULL);
INSERT INTO my_table VALUES (2, 1, 2, NULL);


But it doesn't behave as expected because according to the documentation, two NULL values are not compared to each other, so both inserts pass without error.



How can I guarantee my unique constraint even if id_C can be NULL in this case?
Actually, the real question is: can I guarantee this kind of uniqueness in "pure sql" or do I have to implement it on a higher level (java in my case)?










share|improve this question















migrated from stackoverflow.com Dec 27 '11 at 14:13


This question came from our site for professional and enthusiast programmers.



















  • So, say you have values (1,2,1) and (1,2,2) in the (A,B,C) columns. Should a (1,2,NULL) be allowed to be added or not?

    – ypercubeᵀᴹ
    Dec 27 '11 at 9:27











  • A and B can't be null but C can be null or any positive integer value. So (1,2,3) and (2,4,null) are valid but (null,2,3) or (1,null,4) are invalid. And [(1,2,null), (1,2,3)] does not break unique constraint but [(1,2, null), (1,2,null)] must break it.

    – Manuel Leduc
    Dec 27 '11 at 9:39






  • 2





    Are there any values that will never appear in those columns (like negative values?)

    – a_horse_with_no_name
    Dec 27 '11 at 10:43











  • You don't have to label your constraints in pg. It'll automagically generate a name. Just FYI.

    – Evan Carroll
    Dec 2 '16 at 20:13
















85















I have a table like the following:



create table my_table (
id int8 not null,
id_A int8 not null,
id_B int8 not null,
id_C int8 null,
constraint pk_my_table primary key (id),
constraint u_constrainte unique (id_A, id_B, id_C)
);


And I want (id_A, id_B, id_C) to be distinct in any situation. So the following two inserts must result in an error:



INSERT INTO my_table VALUES (1, 1, 2, NULL);
INSERT INTO my_table VALUES (2, 1, 2, NULL);


But it doesn't behave as expected because according to the documentation, two NULL values are not compared to each other, so both inserts pass without error.



How can I guarantee my unique constraint even if id_C can be NULL in this case?
Actually, the real question is: can I guarantee this kind of uniqueness in "pure sql" or do I have to implement it on a higher level (java in my case)?










share|improve this question















migrated from stackoverflow.com Dec 27 '11 at 14:13


This question came from our site for professional and enthusiast programmers.



















  • So, say you have values (1,2,1) and (1,2,2) in the (A,B,C) columns. Should a (1,2,NULL) be allowed to be added or not?

    – ypercubeᵀᴹ
    Dec 27 '11 at 9:27











  • A and B can't be null but C can be null or any positive integer value. So (1,2,3) and (2,4,null) are valid but (null,2,3) or (1,null,4) are invalid. And [(1,2,null), (1,2,3)] does not break unique constraint but [(1,2, null), (1,2,null)] must break it.

    – Manuel Leduc
    Dec 27 '11 at 9:39






  • 2





    Are there any values that will never appear in those columns (like negative values?)

    – a_horse_with_no_name
    Dec 27 '11 at 10:43











  • You don't have to label your constraints in pg. It'll automagically generate a name. Just FYI.

    – Evan Carroll
    Dec 2 '16 at 20:13














85












85








85


23






I have a table like the following:



create table my_table (
id int8 not null,
id_A int8 not null,
id_B int8 not null,
id_C int8 null,
constraint pk_my_table primary key (id),
constraint u_constrainte unique (id_A, id_B, id_C)
);


And I want (id_A, id_B, id_C) to be distinct in any situation. So the following two inserts must result in an error:



INSERT INTO my_table VALUES (1, 1, 2, NULL);
INSERT INTO my_table VALUES (2, 1, 2, NULL);


But it doesn't behave as expected because according to the documentation, two NULL values are not compared to each other, so both inserts pass without error.



How can I guarantee my unique constraint even if id_C can be NULL in this case?
Actually, the real question is: can I guarantee this kind of uniqueness in "pure sql" or do I have to implement it on a higher level (java in my case)?










share|improve this question
















I have a table like the following:



create table my_table (
id int8 not null,
id_A int8 not null,
id_B int8 not null,
id_C int8 null,
constraint pk_my_table primary key (id),
constraint u_constrainte unique (id_A, id_B, id_C)
);


And I want (id_A, id_B, id_C) to be distinct in any situation. So the following two inserts must result in an error:



INSERT INTO my_table VALUES (1, 1, 2, NULL);
INSERT INTO my_table VALUES (2, 1, 2, NULL);


But it doesn't behave as expected because according to the documentation, two NULL values are not compared to each other, so both inserts pass without error.



How can I guarantee my unique constraint even if id_C can be NULL in this case?
Actually, the real question is: can I guarantee this kind of uniqueness in "pure sql" or do I have to implement it on a higher level (java in my case)?







postgresql constraint null unique-key






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited Sep 5 '14 at 22:44









Marcio Mazzucato

1034




1034










asked Dec 27 '11 at 9:10









Manuel LeducManuel Leduc

531145




531145




migrated from stackoverflow.com Dec 27 '11 at 14:13


This question came from our site for professional and enthusiast programmers.









migrated from stackoverflow.com Dec 27 '11 at 14:13


This question came from our site for professional and enthusiast programmers.















  • So, say you have values (1,2,1) and (1,2,2) in the (A,B,C) columns. Should a (1,2,NULL) be allowed to be added or not?

    – ypercubeᵀᴹ
    Dec 27 '11 at 9:27











  • A and B can't be null but C can be null or any positive integer value. So (1,2,3) and (2,4,null) are valid but (null,2,3) or (1,null,4) are invalid. And [(1,2,null), (1,2,3)] does not break unique constraint but [(1,2, null), (1,2,null)] must break it.

    – Manuel Leduc
    Dec 27 '11 at 9:39






  • 2





    Are there any values that will never appear in those columns (like negative values?)

    – a_horse_with_no_name
    Dec 27 '11 at 10:43











  • You don't have to label your constraints in pg. It'll automagically generate a name. Just FYI.

    – Evan Carroll
    Dec 2 '16 at 20:13



















  • So, say you have values (1,2,1) and (1,2,2) in the (A,B,C) columns. Should a (1,2,NULL) be allowed to be added or not?

    – ypercubeᵀᴹ
    Dec 27 '11 at 9:27











  • A and B can't be null but C can be null or any positive integer value. So (1,2,3) and (2,4,null) are valid but (null,2,3) or (1,null,4) are invalid. And [(1,2,null), (1,2,3)] does not break unique constraint but [(1,2, null), (1,2,null)] must break it.

    – Manuel Leduc
    Dec 27 '11 at 9:39






  • 2





    Are there any values that will never appear in those columns (like negative values?)

    – a_horse_with_no_name
    Dec 27 '11 at 10:43











  • You don't have to label your constraints in pg. It'll automagically generate a name. Just FYI.

    – Evan Carroll
    Dec 2 '16 at 20:13

















So, say you have values (1,2,1) and (1,2,2) in the (A,B,C) columns. Should a (1,2,NULL) be allowed to be added or not?

– ypercubeᵀᴹ
Dec 27 '11 at 9:27





So, say you have values (1,2,1) and (1,2,2) in the (A,B,C) columns. Should a (1,2,NULL) be allowed to be added or not?

– ypercubeᵀᴹ
Dec 27 '11 at 9:27













A and B can't be null but C can be null or any positive integer value. So (1,2,3) and (2,4,null) are valid but (null,2,3) or (1,null,4) are invalid. And [(1,2,null), (1,2,3)] does not break unique constraint but [(1,2, null), (1,2,null)] must break it.

– Manuel Leduc
Dec 27 '11 at 9:39





A and B can't be null but C can be null or any positive integer value. So (1,2,3) and (2,4,null) are valid but (null,2,3) or (1,null,4) are invalid. And [(1,2,null), (1,2,3)] does not break unique constraint but [(1,2, null), (1,2,null)] must break it.

– Manuel Leduc
Dec 27 '11 at 9:39




2




2





Are there any values that will never appear in those columns (like negative values?)

– a_horse_with_no_name
Dec 27 '11 at 10:43





Are there any values that will never appear in those columns (like negative values?)

– a_horse_with_no_name
Dec 27 '11 at 10:43













You don't have to label your constraints in pg. It'll automagically generate a name. Just FYI.

– Evan Carroll
Dec 2 '16 at 20:13





You don't have to label your constraints in pg. It'll automagically generate a name. Just FYI.

– Evan Carroll
Dec 2 '16 at 20:13










3 Answers
3






active

oldest

votes


















86














You can do that in pure SQL. Create a partial unique index in addition to the one you have:



CREATE UNIQUE INDEX ab_c_null_idx ON my_table (id_A, id_B) WHERE id_C IS NULL;


This way you can enter for (a, b, c) in your table:



(1, 2, 1)
(1, 2, 2)
(1, 2, NULL)


But none of these a second time.



Or use two partial UNIQUE indexes and no complete index (or constraint). The best solution depends on the details of your requirements. Compare:




  • Create unique constraint with null columns


Asides



No use for mixed case identifiers without double quotes in PostgreSQL.



You might consider a serial column as primary key or an IDENTITY column in Postgres 10 or later. Related:




  • Auto increment table column


So:



CREATE TABLE my_table (
my_table_id bigint GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY -- for pg 10+
-- my_table_id bigserial PRIMARY KEY -- for pg 9.6 or older
, id_a int8 NOT NULL
, id_b int8 NOT NULL
, id_c int8
, CONSTRAINT u_constraint UNIQUE (id_a, id_b, id_c)
);


If you don't expect more than 2 billion rows (> 2147483647) over the lifetime of your table (including waste and deleted rows), consider integer (4 bytes) instead of bigint (8 bytes).






share|improve this answer


























  • The docs advocate this method, Adding a unique constraint will automatically create a unique B-tree index on the column or group of columns listed in the constraint. A uniqueness restriction covering only some rows cannot be written as a unique constraint, but it is possible to enforce such a restriction by creating a unique partial index.

    – Evan Carroll
    Dec 2 '16 at 20:21





















12














I had the same problem and I found another way to have unique NULL into the table.



CREATE UNIQUE INDEX index_name ON table_name( COALESCE( foreign_key_field, -1) )


In my case, the field foreign_key_field is a positive integer and will never be -1.



So, to answer Manual Leduc, another solution could be



CREATE UNIQUE INDEX  u_constrainte UNIQUE(COALESCE(id_a, -1), COALESCE(id_b,-1),COALESCE(id_c, -1) )


I assume that ids won't be -1.



What is the advantage on creating a partial index ?

In case where you don't have the NOT NULL clause, id_a, id_b and id_c can be NULL together only once.

With a partial index, the 3 fields could be NULL more than once.






share|improve this answer



















  • 3





    > What is the advantage on creating a partial index ? The way you've done it with COALESCE can be effective in restricting the duplicates, but the index wouldn't be very useful in querying as its an expression index that probably won't match query expressions. That is, unless you SELECT COALESCE(col, -1) ... you wouldn't be hitting the index.

    – Bo Jeanes
    Aug 5 '16 at 4:58













  • @BoJeanes The index has not been created for a performance issue. It has been created to fullfill the business requirement.

    – Luc M
    Aug 5 '16 at 19:51



















8














A Null can mean that value is not known for that row at the moment but will be added, when known, in the future (example FinishDate for a running Project) or that no value can be applied for that row (example EscapeVelocity for a black hole Star).



In my opinion, it's usually better to normalize the tables by eliminating all Nulls.



In your case, you want to allow NULLs in your column, yet you want only one NULL to be allowed. Why? What kind of relationship is this between the two tables?



Perhaps you can simply change the column to NOT NULL and store, instead of NULL, a special value (like -1) that is known never to appear. This will solve the uniqueness constraint problem (but may have other possibly unwanted side effects. For example, using -1 to mean "not known / does not apply" will skew any sum or average calculations on the column. Or all such calculations will have to take into account the special value and ignore it.)






share|improve this answer





















  • 1





    In my case NULL is really NULL (id_C is a foreign key to table_c for exemple so it can't have -1 value), it means their is no relationship between "my_table" and "table_c". So it has a functional signification. By the way [(1, 1,1,null), (2, 1,2,null), (3,2,4,null)] is a valid list of inserted data.

    – Manuel Leduc
    Dec 28 '11 at 9:40






  • 1





    It's not really a Null as used in SQL because you want only one in all rows. You could change your database schema either by adding the -1 to table_c or by adding another table (which would be supertype to subtype table_c).

    – ypercubeᵀᴹ
    Dec 28 '11 at 9:48








  • 3





    I'd just like to point out to @Manuel that the opinion on nulls in this answer is not universally held, and is much debated. Many, like me, think that null can be used for any purpose you wish (but should only mean one thing for each field and be documented, possibly in the field name or a column comment)

    – Jack Douglas
    Dec 29 '11 at 7:03






  • 1





    You can't use a dummy value when your column is a FOREIGN KEY.

    – Luc M
    May 17 '12 at 18:42






  • 1





    +1 I am with you: if we want some combination of columns to be unique, then you need to consider an entity in which this combination of columns is a PK. The OPs' database schema should probably change to a parent table and a child one.

    – A-K
    Nov 11 '13 at 22:23











Your Answer








StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "182"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);

StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});

function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: false,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: null,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});


}
});














draft saved

draft discarded


















StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fdba.stackexchange.com%2fquestions%2f9759%2fpostgresql-multi-column-unique-constraint-and-null-values%23new-answer', 'question_page');
}
);

Post as a guest















Required, but never shown

























3 Answers
3






active

oldest

votes








3 Answers
3






active

oldest

votes









active

oldest

votes






active

oldest

votes









86














You can do that in pure SQL. Create a partial unique index in addition to the one you have:



CREATE UNIQUE INDEX ab_c_null_idx ON my_table (id_A, id_B) WHERE id_C IS NULL;


This way you can enter for (a, b, c) in your table:



(1, 2, 1)
(1, 2, 2)
(1, 2, NULL)


But none of these a second time.



Or use two partial UNIQUE indexes and no complete index (or constraint). The best solution depends on the details of your requirements. Compare:




  • Create unique constraint with null columns


Asides



No use for mixed case identifiers without double quotes in PostgreSQL.



You might consider a serial column as primary key or an IDENTITY column in Postgres 10 or later. Related:




  • Auto increment table column


So:



CREATE TABLE my_table (
my_table_id bigint GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY -- for pg 10+
-- my_table_id bigserial PRIMARY KEY -- for pg 9.6 or older
, id_a int8 NOT NULL
, id_b int8 NOT NULL
, id_c int8
, CONSTRAINT u_constraint UNIQUE (id_a, id_b, id_c)
);


If you don't expect more than 2 billion rows (> 2147483647) over the lifetime of your table (including waste and deleted rows), consider integer (4 bytes) instead of bigint (8 bytes).






share|improve this answer


























  • The docs advocate this method, Adding a unique constraint will automatically create a unique B-tree index on the column or group of columns listed in the constraint. A uniqueness restriction covering only some rows cannot be written as a unique constraint, but it is possible to enforce such a restriction by creating a unique partial index.

    – Evan Carroll
    Dec 2 '16 at 20:21


















86














You can do that in pure SQL. Create a partial unique index in addition to the one you have:



CREATE UNIQUE INDEX ab_c_null_idx ON my_table (id_A, id_B) WHERE id_C IS NULL;


This way you can enter for (a, b, c) in your table:



(1, 2, 1)
(1, 2, 2)
(1, 2, NULL)


But none of these a second time.



Or use two partial UNIQUE indexes and no complete index (or constraint). The best solution depends on the details of your requirements. Compare:




  • Create unique constraint with null columns


Asides



No use for mixed case identifiers without double quotes in PostgreSQL.



You might consider a serial column as primary key or an IDENTITY column in Postgres 10 or later. Related:




  • Auto increment table column


So:



CREATE TABLE my_table (
my_table_id bigint GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY -- for pg 10+
-- my_table_id bigserial PRIMARY KEY -- for pg 9.6 or older
, id_a int8 NOT NULL
, id_b int8 NOT NULL
, id_c int8
, CONSTRAINT u_constraint UNIQUE (id_a, id_b, id_c)
);


If you don't expect more than 2 billion rows (> 2147483647) over the lifetime of your table (including waste and deleted rows), consider integer (4 bytes) instead of bigint (8 bytes).






share|improve this answer


























  • The docs advocate this method, Adding a unique constraint will automatically create a unique B-tree index on the column or group of columns listed in the constraint. A uniqueness restriction covering only some rows cannot be written as a unique constraint, but it is possible to enforce such a restriction by creating a unique partial index.

    – Evan Carroll
    Dec 2 '16 at 20:21
















86












86








86







You can do that in pure SQL. Create a partial unique index in addition to the one you have:



CREATE UNIQUE INDEX ab_c_null_idx ON my_table (id_A, id_B) WHERE id_C IS NULL;


This way you can enter for (a, b, c) in your table:



(1, 2, 1)
(1, 2, 2)
(1, 2, NULL)


But none of these a second time.



Or use two partial UNIQUE indexes and no complete index (or constraint). The best solution depends on the details of your requirements. Compare:




  • Create unique constraint with null columns


Asides



No use for mixed case identifiers without double quotes in PostgreSQL.



You might consider a serial column as primary key or an IDENTITY column in Postgres 10 or later. Related:




  • Auto increment table column


So:



CREATE TABLE my_table (
my_table_id bigint GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY -- for pg 10+
-- my_table_id bigserial PRIMARY KEY -- for pg 9.6 or older
, id_a int8 NOT NULL
, id_b int8 NOT NULL
, id_c int8
, CONSTRAINT u_constraint UNIQUE (id_a, id_b, id_c)
);


If you don't expect more than 2 billion rows (> 2147483647) over the lifetime of your table (including waste and deleted rows), consider integer (4 bytes) instead of bigint (8 bytes).






share|improve this answer















You can do that in pure SQL. Create a partial unique index in addition to the one you have:



CREATE UNIQUE INDEX ab_c_null_idx ON my_table (id_A, id_B) WHERE id_C IS NULL;


This way you can enter for (a, b, c) in your table:



(1, 2, 1)
(1, 2, 2)
(1, 2, NULL)


But none of these a second time.



Or use two partial UNIQUE indexes and no complete index (or constraint). The best solution depends on the details of your requirements. Compare:




  • Create unique constraint with null columns


Asides



No use for mixed case identifiers without double quotes in PostgreSQL.



You might consider a serial column as primary key or an IDENTITY column in Postgres 10 or later. Related:




  • Auto increment table column


So:



CREATE TABLE my_table (
my_table_id bigint GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY -- for pg 10+
-- my_table_id bigserial PRIMARY KEY -- for pg 9.6 or older
, id_a int8 NOT NULL
, id_b int8 NOT NULL
, id_c int8
, CONSTRAINT u_constraint UNIQUE (id_a, id_b, id_c)
);


If you don't expect more than 2 billion rows (> 2147483647) over the lifetime of your table (including waste and deleted rows), consider integer (4 bytes) instead of bigint (8 bytes).







share|improve this answer














share|improve this answer



share|improve this answer








edited 4 mins ago

























answered Dec 27 '11 at 10:51









Erwin BrandstetterErwin Brandstetter

93k9178292




93k9178292













  • The docs advocate this method, Adding a unique constraint will automatically create a unique B-tree index on the column or group of columns listed in the constraint. A uniqueness restriction covering only some rows cannot be written as a unique constraint, but it is possible to enforce such a restriction by creating a unique partial index.

    – Evan Carroll
    Dec 2 '16 at 20:21





















  • The docs advocate this method, Adding a unique constraint will automatically create a unique B-tree index on the column or group of columns listed in the constraint. A uniqueness restriction covering only some rows cannot be written as a unique constraint, but it is possible to enforce such a restriction by creating a unique partial index.

    – Evan Carroll
    Dec 2 '16 at 20:21



















The docs advocate this method, Adding a unique constraint will automatically create a unique B-tree index on the column or group of columns listed in the constraint. A uniqueness restriction covering only some rows cannot be written as a unique constraint, but it is possible to enforce such a restriction by creating a unique partial index.

– Evan Carroll
Dec 2 '16 at 20:21







The docs advocate this method, Adding a unique constraint will automatically create a unique B-tree index on the column or group of columns listed in the constraint. A uniqueness restriction covering only some rows cannot be written as a unique constraint, but it is possible to enforce such a restriction by creating a unique partial index.

– Evan Carroll
Dec 2 '16 at 20:21















12














I had the same problem and I found another way to have unique NULL into the table.



CREATE UNIQUE INDEX index_name ON table_name( COALESCE( foreign_key_field, -1) )


In my case, the field foreign_key_field is a positive integer and will never be -1.



So, to answer Manual Leduc, another solution could be



CREATE UNIQUE INDEX  u_constrainte UNIQUE(COALESCE(id_a, -1), COALESCE(id_b,-1),COALESCE(id_c, -1) )


I assume that ids won't be -1.



What is the advantage on creating a partial index ?

In case where you don't have the NOT NULL clause, id_a, id_b and id_c can be NULL together only once.

With a partial index, the 3 fields could be NULL more than once.






share|improve this answer



















  • 3





    > What is the advantage on creating a partial index ? The way you've done it with COALESCE can be effective in restricting the duplicates, but the index wouldn't be very useful in querying as its an expression index that probably won't match query expressions. That is, unless you SELECT COALESCE(col, -1) ... you wouldn't be hitting the index.

    – Bo Jeanes
    Aug 5 '16 at 4:58













  • @BoJeanes The index has not been created for a performance issue. It has been created to fullfill the business requirement.

    – Luc M
    Aug 5 '16 at 19:51
















12














I had the same problem and I found another way to have unique NULL into the table.



CREATE UNIQUE INDEX index_name ON table_name( COALESCE( foreign_key_field, -1) )


In my case, the field foreign_key_field is a positive integer and will never be -1.



So, to answer Manual Leduc, another solution could be



CREATE UNIQUE INDEX  u_constrainte UNIQUE(COALESCE(id_a, -1), COALESCE(id_b,-1),COALESCE(id_c, -1) )


I assume that ids won't be -1.



What is the advantage on creating a partial index ?

In case where you don't have the NOT NULL clause, id_a, id_b and id_c can be NULL together only once.

With a partial index, the 3 fields could be NULL more than once.






share|improve this answer



















  • 3





    > What is the advantage on creating a partial index ? The way you've done it with COALESCE can be effective in restricting the duplicates, but the index wouldn't be very useful in querying as its an expression index that probably won't match query expressions. That is, unless you SELECT COALESCE(col, -1) ... you wouldn't be hitting the index.

    – Bo Jeanes
    Aug 5 '16 at 4:58













  • @BoJeanes The index has not been created for a performance issue. It has been created to fullfill the business requirement.

    – Luc M
    Aug 5 '16 at 19:51














12












12








12







I had the same problem and I found another way to have unique NULL into the table.



CREATE UNIQUE INDEX index_name ON table_name( COALESCE( foreign_key_field, -1) )


In my case, the field foreign_key_field is a positive integer and will never be -1.



So, to answer Manual Leduc, another solution could be



CREATE UNIQUE INDEX  u_constrainte UNIQUE(COALESCE(id_a, -1), COALESCE(id_b,-1),COALESCE(id_c, -1) )


I assume that ids won't be -1.



What is the advantage on creating a partial index ?

In case where you don't have the NOT NULL clause, id_a, id_b and id_c can be NULL together only once.

With a partial index, the 3 fields could be NULL more than once.






share|improve this answer













I had the same problem and I found another way to have unique NULL into the table.



CREATE UNIQUE INDEX index_name ON table_name( COALESCE( foreign_key_field, -1) )


In my case, the field foreign_key_field is a positive integer and will never be -1.



So, to answer Manual Leduc, another solution could be



CREATE UNIQUE INDEX  u_constrainte UNIQUE(COALESCE(id_a, -1), COALESCE(id_b,-1),COALESCE(id_c, -1) )


I assume that ids won't be -1.



What is the advantage on creating a partial index ?

In case where you don't have the NOT NULL clause, id_a, id_b and id_c can be NULL together only once.

With a partial index, the 3 fields could be NULL more than once.







share|improve this answer












share|improve this answer



share|improve this answer










answered May 17 '12 at 20:57









Luc MLuc M

3441411




3441411








  • 3





    > What is the advantage on creating a partial index ? The way you've done it with COALESCE can be effective in restricting the duplicates, but the index wouldn't be very useful in querying as its an expression index that probably won't match query expressions. That is, unless you SELECT COALESCE(col, -1) ... you wouldn't be hitting the index.

    – Bo Jeanes
    Aug 5 '16 at 4:58













  • @BoJeanes The index has not been created for a performance issue. It has been created to fullfill the business requirement.

    – Luc M
    Aug 5 '16 at 19:51














  • 3





    > What is the advantage on creating a partial index ? The way you've done it with COALESCE can be effective in restricting the duplicates, but the index wouldn't be very useful in querying as its an expression index that probably won't match query expressions. That is, unless you SELECT COALESCE(col, -1) ... you wouldn't be hitting the index.

    – Bo Jeanes
    Aug 5 '16 at 4:58













  • @BoJeanes The index has not been created for a performance issue. It has been created to fullfill the business requirement.

    – Luc M
    Aug 5 '16 at 19:51








3




3





> What is the advantage on creating a partial index ? The way you've done it with COALESCE can be effective in restricting the duplicates, but the index wouldn't be very useful in querying as its an expression index that probably won't match query expressions. That is, unless you SELECT COALESCE(col, -1) ... you wouldn't be hitting the index.

– Bo Jeanes
Aug 5 '16 at 4:58







> What is the advantage on creating a partial index ? The way you've done it with COALESCE can be effective in restricting the duplicates, but the index wouldn't be very useful in querying as its an expression index that probably won't match query expressions. That is, unless you SELECT COALESCE(col, -1) ... you wouldn't be hitting the index.

– Bo Jeanes
Aug 5 '16 at 4:58















@BoJeanes The index has not been created for a performance issue. It has been created to fullfill the business requirement.

– Luc M
Aug 5 '16 at 19:51





@BoJeanes The index has not been created for a performance issue. It has been created to fullfill the business requirement.

– Luc M
Aug 5 '16 at 19:51











8














A Null can mean that value is not known for that row at the moment but will be added, when known, in the future (example FinishDate for a running Project) or that no value can be applied for that row (example EscapeVelocity for a black hole Star).



In my opinion, it's usually better to normalize the tables by eliminating all Nulls.



In your case, you want to allow NULLs in your column, yet you want only one NULL to be allowed. Why? What kind of relationship is this between the two tables?



Perhaps you can simply change the column to NOT NULL and store, instead of NULL, a special value (like -1) that is known never to appear. This will solve the uniqueness constraint problem (but may have other possibly unwanted side effects. For example, using -1 to mean "not known / does not apply" will skew any sum or average calculations on the column. Or all such calculations will have to take into account the special value and ignore it.)






share|improve this answer





















  • 1





    In my case NULL is really NULL (id_C is a foreign key to table_c for exemple so it can't have -1 value), it means their is no relationship between "my_table" and "table_c". So it has a functional signification. By the way [(1, 1,1,null), (2, 1,2,null), (3,2,4,null)] is a valid list of inserted data.

    – Manuel Leduc
    Dec 28 '11 at 9:40






  • 1





    It's not really a Null as used in SQL because you want only one in all rows. You could change your database schema either by adding the -1 to table_c or by adding another table (which would be supertype to subtype table_c).

    – ypercubeᵀᴹ
    Dec 28 '11 at 9:48








  • 3





    I'd just like to point out to @Manuel that the opinion on nulls in this answer is not universally held, and is much debated. Many, like me, think that null can be used for any purpose you wish (but should only mean one thing for each field and be documented, possibly in the field name or a column comment)

    – Jack Douglas
    Dec 29 '11 at 7:03






  • 1





    You can't use a dummy value when your column is a FOREIGN KEY.

    – Luc M
    May 17 '12 at 18:42






  • 1





    +1 I am with you: if we want some combination of columns to be unique, then you need to consider an entity in which this combination of columns is a PK. The OPs' database schema should probably change to a parent table and a child one.

    – A-K
    Nov 11 '13 at 22:23
















8














A Null can mean that value is not known for that row at the moment but will be added, when known, in the future (example FinishDate for a running Project) or that no value can be applied for that row (example EscapeVelocity for a black hole Star).



In my opinion, it's usually better to normalize the tables by eliminating all Nulls.



In your case, you want to allow NULLs in your column, yet you want only one NULL to be allowed. Why? What kind of relationship is this between the two tables?



Perhaps you can simply change the column to NOT NULL and store, instead of NULL, a special value (like -1) that is known never to appear. This will solve the uniqueness constraint problem (but may have other possibly unwanted side effects. For example, using -1 to mean "not known / does not apply" will skew any sum or average calculations on the column. Or all such calculations will have to take into account the special value and ignore it.)






share|improve this answer





















  • 1





    In my case NULL is really NULL (id_C is a foreign key to table_c for exemple so it can't have -1 value), it means their is no relationship between "my_table" and "table_c". So it has a functional signification. By the way [(1, 1,1,null), (2, 1,2,null), (3,2,4,null)] is a valid list of inserted data.

    – Manuel Leduc
    Dec 28 '11 at 9:40






  • 1





    It's not really a Null as used in SQL because you want only one in all rows. You could change your database schema either by adding the -1 to table_c or by adding another table (which would be supertype to subtype table_c).

    – ypercubeᵀᴹ
    Dec 28 '11 at 9:48








  • 3





    I'd just like to point out to @Manuel that the opinion on nulls in this answer is not universally held, and is much debated. Many, like me, think that null can be used for any purpose you wish (but should only mean one thing for each field and be documented, possibly in the field name or a column comment)

    – Jack Douglas
    Dec 29 '11 at 7:03






  • 1





    You can't use a dummy value when your column is a FOREIGN KEY.

    – Luc M
    May 17 '12 at 18:42






  • 1





    +1 I am with you: if we want some combination of columns to be unique, then you need to consider an entity in which this combination of columns is a PK. The OPs' database schema should probably change to a parent table and a child one.

    – A-K
    Nov 11 '13 at 22:23














8












8








8







A Null can mean that value is not known for that row at the moment but will be added, when known, in the future (example FinishDate for a running Project) or that no value can be applied for that row (example EscapeVelocity for a black hole Star).



In my opinion, it's usually better to normalize the tables by eliminating all Nulls.



In your case, you want to allow NULLs in your column, yet you want only one NULL to be allowed. Why? What kind of relationship is this between the two tables?



Perhaps you can simply change the column to NOT NULL and store, instead of NULL, a special value (like -1) that is known never to appear. This will solve the uniqueness constraint problem (but may have other possibly unwanted side effects. For example, using -1 to mean "not known / does not apply" will skew any sum or average calculations on the column. Or all such calculations will have to take into account the special value and ignore it.)






share|improve this answer















A Null can mean that value is not known for that row at the moment but will be added, when known, in the future (example FinishDate for a running Project) or that no value can be applied for that row (example EscapeVelocity for a black hole Star).



In my opinion, it's usually better to normalize the tables by eliminating all Nulls.



In your case, you want to allow NULLs in your column, yet you want only one NULL to be allowed. Why? What kind of relationship is this between the two tables?



Perhaps you can simply change the column to NOT NULL and store, instead of NULL, a special value (like -1) that is known never to appear. This will solve the uniqueness constraint problem (but may have other possibly unwanted side effects. For example, using -1 to mean "not known / does not apply" will skew any sum or average calculations on the column. Or all such calculations will have to take into account the special value and ignore it.)







share|improve this answer














share|improve this answer



share|improve this answer








edited Feb 9 at 16:43

























answered Dec 28 '11 at 0:09









ypercubeᵀᴹypercubeᵀᴹ

76.8k11133214




76.8k11133214








  • 1





    In my case NULL is really NULL (id_C is a foreign key to table_c for exemple so it can't have -1 value), it means their is no relationship between "my_table" and "table_c". So it has a functional signification. By the way [(1, 1,1,null), (2, 1,2,null), (3,2,4,null)] is a valid list of inserted data.

    – Manuel Leduc
    Dec 28 '11 at 9:40






  • 1





    It's not really a Null as used in SQL because you want only one in all rows. You could change your database schema either by adding the -1 to table_c or by adding another table (which would be supertype to subtype table_c).

    – ypercubeᵀᴹ
    Dec 28 '11 at 9:48








  • 3





    I'd just like to point out to @Manuel that the opinion on nulls in this answer is not universally held, and is much debated. Many, like me, think that null can be used for any purpose you wish (but should only mean one thing for each field and be documented, possibly in the field name or a column comment)

    – Jack Douglas
    Dec 29 '11 at 7:03






  • 1





    You can't use a dummy value when your column is a FOREIGN KEY.

    – Luc M
    May 17 '12 at 18:42






  • 1





    +1 I am with you: if we want some combination of columns to be unique, then you need to consider an entity in which this combination of columns is a PK. The OPs' database schema should probably change to a parent table and a child one.

    – A-K
    Nov 11 '13 at 22:23














  • 1





    In my case NULL is really NULL (id_C is a foreign key to table_c for exemple so it can't have -1 value), it means their is no relationship between "my_table" and "table_c". So it has a functional signification. By the way [(1, 1,1,null), (2, 1,2,null), (3,2,4,null)] is a valid list of inserted data.

    – Manuel Leduc
    Dec 28 '11 at 9:40






  • 1





    It's not really a Null as used in SQL because you want only one in all rows. You could change your database schema either by adding the -1 to table_c or by adding another table (which would be supertype to subtype table_c).

    – ypercubeᵀᴹ
    Dec 28 '11 at 9:48








  • 3





    I'd just like to point out to @Manuel that the opinion on nulls in this answer is not universally held, and is much debated. Many, like me, think that null can be used for any purpose you wish (but should only mean one thing for each field and be documented, possibly in the field name or a column comment)

    – Jack Douglas
    Dec 29 '11 at 7:03






  • 1





    You can't use a dummy value when your column is a FOREIGN KEY.

    – Luc M
    May 17 '12 at 18:42






  • 1





    +1 I am with you: if we want some combination of columns to be unique, then you need to consider an entity in which this combination of columns is a PK. The OPs' database schema should probably change to a parent table and a child one.

    – A-K
    Nov 11 '13 at 22:23








1




1





In my case NULL is really NULL (id_C is a foreign key to table_c for exemple so it can't have -1 value), it means their is no relationship between "my_table" and "table_c". So it has a functional signification. By the way [(1, 1,1,null), (2, 1,2,null), (3,2,4,null)] is a valid list of inserted data.

– Manuel Leduc
Dec 28 '11 at 9:40





In my case NULL is really NULL (id_C is a foreign key to table_c for exemple so it can't have -1 value), it means their is no relationship between "my_table" and "table_c". So it has a functional signification. By the way [(1, 1,1,null), (2, 1,2,null), (3,2,4,null)] is a valid list of inserted data.

– Manuel Leduc
Dec 28 '11 at 9:40




1




1





It's not really a Null as used in SQL because you want only one in all rows. You could change your database schema either by adding the -1 to table_c or by adding another table (which would be supertype to subtype table_c).

– ypercubeᵀᴹ
Dec 28 '11 at 9:48







It's not really a Null as used in SQL because you want only one in all rows. You could change your database schema either by adding the -1 to table_c or by adding another table (which would be supertype to subtype table_c).

– ypercubeᵀᴹ
Dec 28 '11 at 9:48






3




3





I'd just like to point out to @Manuel that the opinion on nulls in this answer is not universally held, and is much debated. Many, like me, think that null can be used for any purpose you wish (but should only mean one thing for each field and be documented, possibly in the field name or a column comment)

– Jack Douglas
Dec 29 '11 at 7:03





I'd just like to point out to @Manuel that the opinion on nulls in this answer is not universally held, and is much debated. Many, like me, think that null can be used for any purpose you wish (but should only mean one thing for each field and be documented, possibly in the field name or a column comment)

– Jack Douglas
Dec 29 '11 at 7:03




1




1





You can't use a dummy value when your column is a FOREIGN KEY.

– Luc M
May 17 '12 at 18:42





You can't use a dummy value when your column is a FOREIGN KEY.

– Luc M
May 17 '12 at 18:42




1




1





+1 I am with you: if we want some combination of columns to be unique, then you need to consider an entity in which this combination of columns is a PK. The OPs' database schema should probably change to a parent table and a child one.

– A-K
Nov 11 '13 at 22:23





+1 I am with you: if we want some combination of columns to be unique, then you need to consider an entity in which this combination of columns is a PK. The OPs' database schema should probably change to a parent table and a child one.

– A-K
Nov 11 '13 at 22:23


















draft saved

draft discarded




















































Thanks for contributing an answer to Database Administrators Stack Exchange!


  • Please be sure to answer the question. Provide details and share your research!

But avoid



  • Asking for help, clarification, or responding to other answers.

  • Making statements based on opinion; back them up with references or personal experience.


To learn more, see our tips on writing great answers.




draft saved


draft discarded














StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fdba.stackexchange.com%2fquestions%2f9759%2fpostgresql-multi-column-unique-constraint-and-null-values%23new-answer', 'question_page');
}
);

Post as a guest















Required, but never shown





















































Required, but never shown














Required, but never shown












Required, but never shown







Required, but never shown

































Required, but never shown














Required, but never shown












Required, but never shown







Required, but never shown







Popular posts from this blog

Szabolcs (Ungheria) Altri progetti | Menu di navigazione48°10′14.56″N 21°29′33.14″E /...

Discografia di Klaus Schulze Indice Album in studio | Album dal vivo | Singoli | Antologie | Colonne...

How to make inet_server_addr() return localhost in spite of ::1/128RETURN NEXT in Postgres FunctionConnect to...