Search Postgresql Archives

Re: Way to create unique constraint in Postgres even with null columns

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Sun, Nov 27, 2011 at 2:18 PM, David Johnston <polobo@xxxxxxxxx> wrote:
> -----Original Message-----
> From: pgsql-general-owner@xxxxxxxxxxxxxx
> [mailto:pgsql-general-owner@xxxxxxxxxxxxxx] On Behalf Of Mike Christensen
> Sent: Sunday, November 27, 2011 5:02 PM
> To: Thomas Kellerer
> Cc: pgsql-general@xxxxxxxxxxxxxx
> Subject: Re:  Way to create unique constraint in Postgres even with
> null columns
>
> On Sun, Nov 27, 2011 at 1:47 PM, Thomas Kellerer <spam_eater@xxxxxxx> wrote:
>> Mike Christensen wrote on 27.11.2011 22:18:
>>>
>>> I have a table with this layout:
>>>
>>>     CREATE TABLE Favorites
>>>     (
>>>       FavoriteId uuid NOT NULL, --Primary key
>>>       UserId uuid NOT NULL,
>>>       RecipeId uuid NOT NULL,
>>>       MenuId uuid
>>>     )
>>>
>>> I want to create a unique constraint similar to this:
>>>
>>>     ALTER TABLE Favorites ADD CONSTRAINT Favorites_UniqueFavorite
>>> UNIQUE(UserId, MenuId, RecipeId);
>>>
>>> However, this will allow multiple rows with the same UserId and
>>> RecipeId, if the MenuId is null.  I want to allow a NULL MenuId to
>>> store a favorite that has no associated menu, but I only want at most
>>> one of these rows per user/recipe pair.
>>
>> In addition to the above unique constraint you will need another one:
>>
>> CREATE UNIQUE INDEX Favorites_UniqueFavorite
>>   ON (UserId, MenuId)
>>   WHERE RecipeId IS NULL;
>
> Excellent solution!  Thanks all..
>
> -------------------------------------------------------------
>
> While the conditional index will work this is one of many situations where
> being explicit is probably the better option.  It is quite likely that you
> will want to use the MenuID in queries and having to deal with NULL in those
> situations is messy.  You should create a "DEFAULT" menu for each user and
> replace any existing NULLs with the DEFAULT MenuID for the given user.
> Then, make the MenuID column "NOT NULL".
>
> Also, the index example above presumes you want RecipeId to be "Null-able"
> as opposed to MenuId as described in your original post.

Yea I assumed the idea was to do something like:

CREATE UNIQUE INDEX IDX_Favorites_NullMenu ON Favorites(UserId,
RecipeId) WHERE MenuId IS NULL;
CREATE UNIQUE INDEX IDX_Favorites_UniqueMenu ON Favorites(UserId,
RecipeId, MenuId) WHERE MenuId IS NOT NULL;

I'm not sure what situations become "messy" when MenuId allows NULLs
though.  Maybe you can provide a few more details?  I do agree
creating a default Menu for each user is the way to go.  However, it
makes inserting a lot more difficult.  If a user adds a recipe to
their favorites, and does not specify a menu, I then have to go lookup
the UUID for their default menu first.  It's not a huge deal, but I'd
like to avoid that if possible.  I think NULL makes sense here since
it really does mean "there is no menu for this row".  Thanks!

Mike

-- 
Sent via pgsql-general mailing list (pgsql-general@xxxxxxxxxxxxxx)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-general



[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Index of Archives]     [Postgresql Jobs]     [Postgresql Admin]     [Postgresql Performance]     [Linux Clusters]     [PHP Home]     [PHP on Windows]     [Kernel Newbies]     [PHP Classes]     [PHP Books]     [PHP Databases]     [Postgresql & PHP]     [Yosemite]
  Powered by Linux