简体   繁体   中英

Postgres non-unique if other field is same, unique otherwise?

I'm looking to do the following:

Create a constraint where a user can claim a unique URL, and they can create as many rows with that URL as they want, but other users cannot use that URL once it's been created once.

Anyone know how I'd do this? Thanks!

You want a URL to be unique to a user but then not unique after that.

If you enumerated each url for a user, you could do this with a filtered/partial index.

create unique index idx_t_user_url_seqnum on t(user, url, seqnum)
    where seqnum = 1;

But, I think the problem is your data model. You are trying to do too much with a single table. I think you should have a mapping table with mappings between urls and users:

create table UserUrlMapping (
    UserUrlMappingId serial primary key,
    UserId int references Users(UserId),
    Url varchar(4000)
    constraint unq_url unique (Url)  -- If you think about it, being in this table once means that there is only one user
);

Then, in your data table, don't put the URL there, put the UserUrlMappingId instead.

First, create a table which associates URLs with users:

CREATE TABLE url_allocations (
    url     text NOT NULL,
    user_id uuid NOT NULL,
    PRIMARY KEY (url),
    FOREIGN KEY (user_id)
        REFERENCES users(id)
        ON DELETE CASCADE
);

Now each URL can only be used by only one user, due to the primary key constraint. Next, create a foreign key to your table:

CREATE TABLE links (
    id      uuid NOT NULL,
    url     text NOT NULL,
    -- ...
    PRIMARY KEY (id),
    FOREIGN KEY (url)
        REFERENCES url_allocations(url)
        ON DELETE RESTRICT
);

The user ID of the link can now be found by joining url_allocations .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM