如何为在 PostgreSQL 中应视为一列的 2 列指定唯一约束?
How do I specify unique constraint for 2 columns that should be treated as one in PostgreSQL?
假设我有一个 table:
table people (
user,
path1,
path2,
);
如果列 path1 或 path2 中已有同名记录,我想限制 adding/updating。
示例:
INSERT INTO people (user, path1, path2)
VALUES ('George', 'New York', 'Toronto',);
INSERT INTO people (user, path1, path2)
VALUES ('Joe', 'Toronto', 'LA',);
在第二次插入时,应该会出现错误,因为'Toronto'已经在第一个记录的path2中定义了。
理论上 exclusion constraint 可以解决这个问题。
但是,下面的代码不起作用:
create table people
(
"user" text,
path1 text,
path2 text
);
alter table people
add constraint check_path
exclude using gist ("user" with =, (array[path1, path2]) with && );
以上导致错误:
ERROR: data type text[] has no default operator class for access method "gist"
But:&&
运算符适用于整数数组。因此,如果“路径”列可以变成一个整数,例如引用查找的外键 table,这可以通过以下方式实现:
create table location
(
id integer primary key,
name varchar(50) not null unique
);
create table people
(
"user" text,
path1 int not null references location,
path2 int not null references location
);
alter table people
add constraint check_path
exclude using gist ("user" with =, (array[path1, path2]) with && );
insert into location (id, name)
values
(1, 'New York'),
(2, 'Toronto'),
(3, 'LA');
那么这个插入显然会起作用:
insert into people ("user", path1, path2)
values
('George', 1, 2);
但这会导致错误:
insert into people ("user", path1, path2)
values ('George', 2, 3);
错误将是:
ERROR: conflicting key value violates exclusion constraint "check_path"
DETAIL: Key ("user", (ARRAY[path1, path2]))=(George, {2,3}) conflicts with existing key ("user", (ARRAY[path1, path2]))=(George, {1,2}).
假设我有一个 table:
table people (
user,
path1,
path2,
);
如果列 path1 或 path2 中已有同名记录,我想限制 adding/updating。
示例:
INSERT INTO people (user, path1, path2)
VALUES ('George', 'New York', 'Toronto',);
INSERT INTO people (user, path1, path2)
VALUES ('Joe', 'Toronto', 'LA',);
在第二次插入时,应该会出现错误,因为'Toronto'已经在第一个记录的path2中定义了。
理论上 exclusion constraint 可以解决这个问题。
但是,下面的代码不起作用:
create table people
(
"user" text,
path1 text,
path2 text
);
alter table people
add constraint check_path
exclude using gist ("user" with =, (array[path1, path2]) with && );
以上导致错误:
ERROR: data type text[] has no default operator class for access method "gist"
But:&&
运算符适用于整数数组。因此,如果“路径”列可以变成一个整数,例如引用查找的外键 table,这可以通过以下方式实现:
create table location
(
id integer primary key,
name varchar(50) not null unique
);
create table people
(
"user" text,
path1 int not null references location,
path2 int not null references location
);
alter table people
add constraint check_path
exclude using gist ("user" with =, (array[path1, path2]) with && );
insert into location (id, name)
values
(1, 'New York'),
(2, 'Toronto'),
(3, 'LA');
那么这个插入显然会起作用:
insert into people ("user", path1, path2)
values
('George', 1, 2);
但这会导致错误:
insert into people ("user", path1, path2)
values ('George', 2, 3);
错误将是:
ERROR: conflicting key value violates exclusion constraint "check_path"
DETAIL: Key ("user", (ARRAY[path1, path2]))=(George, {2,3}) conflicts with existing key ("user", (ARRAY[path1, path2]))=(George, {1,2}).