3

I have some tables, let's say 2 for simplicity:

CREATE TABLE A (
    name varchar
    ...
);
CREATE TABLE B (
    name varchar
    ...
);

These tables have different structures but all have the same column (name)

I want to add a unique constraint on all of these columns in all of these tables.

How can I do this? This seems like a simple thing but my googling haven't proven successful so far. Most existing questions seem to deal with multiple columns in the same table.

3
  • So, do you want that a name inserted in table A could not be inserted in table B (or C, or D, ...)? Commented May 7, 2020 at 2:47
  • That's right, the values in all those columns in all those tables should all be unique. Commented May 7, 2020 at 2:50
  • This can also be viewed as PostgreSQL inheritance, where the name property belongs to the abstract entity and it's UNIQUE there. Commented May 7, 2020 at 3:10

1 Answer 1

2

Since UNIQUE constraints cannot span multiple tables, you'll need to create an extra table to store all the names. Then each table will have a foreign key against the extra table.

For example:

create table all_names (
  zone int not null,
  name varchar(20) not null,
  constraint uq1 unique (zone, name),
  constraint uq2 unique (name) -- this is the critical constraint!
);

create table a (
  zone int not null default 1 check (zone = 1),
  name varchar(20) not null,
  constraint fk1 foreign key (zone, name) references all_names (zone, name)
);

insert into all_names (zone, name) values (1, 'Jenny'); -- succeeds
insert into a (name) values ('Jenny'); -- succeeds

create table b (
  zone int not null default 2 check (zone = 2),
  name varchar(20) not null,
  constraint fk2 foreign key (zone, name) references all_names (zone, name)
);

insert into all_names (zone, name) values (2, 'Ivan'); -- succeeds
insert into b (name) values ('Ivan'); -- succeeds

insert into all_names (zone, name) values (2, 'Jenny'); -- fails!
insert into b (name) values ('Jenny'); -- fails!

Note that each insert now requires an extra insert in the extra all_names table. This can, however, be automated (and happen behind the scenes) by the use of a pre/post-insert trigger (not shown).

See running example at DB Fiddle.

If you implement a trigger, then your inserts will look simple, as in:

insert into a (name) values ('Jenny'); -- succeeds
insert into b (name) values ('Ivan'); -- succeeds
insert into b (name) values ('Jenny'); -- fails!
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.