Postgres连接表的唯一多列索引

blo*_*ilk 4 sql postgresql join

我在Postgres中有一个多对多的连接表,我想索引到A)提高性能(显然)和B)强制唯一性.例如:

a_id | b_id
1    | 2     <- okay
1    | 3     <- okay
2    | 3     <- okay
1    | 3     <- not okay (same as row 2)
Run Code Online (Sandbox Code Playgroud)

是否可以在两列上使用单个索引来强制值中的唯一性?我应该使用什么类型的索引?

Mic*_*uen 11

作为主键

如果唯一是主键,请执行此操作:

create table tbl(
   a_id int not null,
   b_id int not null,
   constraint tbl_pkey primary key(a_id,b_id)
);
Run Code Online (Sandbox Code Playgroud)

不是主键

如果该唯一是非主键,请执行此操作:

create table tbl(

   -- other primary key here, e.g.:
   -- id serial primary key,

   a_id int not null,
   b_id int not null,
   constraint tbl_unique unique(a_id,b_id)
);
Run Code Online (Sandbox Code Playgroud)

现有表格

如果您有现有表,请改为:

alter table tbl
      add constraint tbl_unique unique(a_id, b_id)
Run Code Online (Sandbox Code Playgroud)

alter table显示以下消息:

NOTICE:  ALTER TABLE / ADD UNIQUE will create implicit index "tbl_unique" for table "tbl"


Query returned successfully with no result in 22 ms.
Run Code Online (Sandbox Code Playgroud)

下降

如果要删除该约束(您可能希望将3个字段组合成唯一):

ALTER TABLE tbl DROP CONSTRAINT tbl_unique;
Run Code Online (Sandbox Code Playgroud)

索引与约束与空白

关于索引,来自Postgres doc:

当为表定义唯一约束或主键时,PostgreSQL会自动创建唯一索引

资料来源:http://www.postgresql.org/docs/9.1/static/indexes-unique.html


如果唯一性取决于某些规则,您应使用CREATE UNIQUE INDEX,例如:

鉴于这种:

CREATE TABLE tbl
(
  a_id integer NOT NULL,
  b_id integer NULL  
);

alter table tbl
    add constraint tbl_unique unique(a_id, b_id);
Run Code Online (Sandbox Code Playgroud)

唯一可以捕获这些重复项,这将被数据库拒绝:

insert into tbl values
(1,1),
(1,1);
Run Code Online (Sandbox Code Playgroud)

然而,UNIQUE CONSTRAINT无法捕获重复的空值.Nulls用作未知数,它们用作通配符,这就是为什么它允许在唯一约束中具有多个空值.这将被数据库接受:

insert into tbl values
(1,1),
(1,null), -- think of this null as wildcard, some real value can be assigned later.
(1,null); -- and so is this. that's why both of these nulls are allowed
Run Code Online (Sandbox Code Playgroud)

可以想象UNIQUE CONSTRAINT它允许延迟唯一性,因此接受上面的空值.

如果每个a_id只需要一个通配符(null b_id),除了唯一约束外,还需要添加一个UNIQUE INDEX.UNIQUE CONSTRAINT不能在它们上面有表达式. INDEX并且UNIQUE INDEX可以.这将是您拒绝多个null的完整DDL;

这将是您完整的DDL:

CREATE TABLE tbl
(
  a_id integer NOT NULL,
  b_id integer NULL  
);
alter table tbl
    add constraint tbl_unique unique(a_id, b_id);

create unique index tbl_unique_a_id on tbl(a_id) where b_id is null;      
Run Code Online (Sandbox Code Playgroud)

现在,您的数据库将拒绝此操作:

insert into tbl values
(1,1),
(1,null),
(1,null);
Run Code Online (Sandbox Code Playgroud)

这将是允许的:

insert into tbl values
(1,1),
(1,null);
Run Code Online (Sandbox Code Playgroud)

http://www.ienablemuch.com/2010/12/postgresql-said-sql-server2008-said-non.html相关

  • 请注意,虽然(a_id,b_id)上的多列索引也可以仅用于搜索a_id,但它不能仅用于b_id上的搜索.因此,您可能希望在b_id上创建第二个单列索引. (2认同)

the*_*ory 5

除了使用@Michael Buen解释的PRIMARY KEYUNIQUE语法之外,您还可以创建一个显式索引:

CREATE UNIQUE INDEX foo_a_b ON tbl(a_id, b_id);
Run Code Online (Sandbox Code Playgroud)

这只是一个普通的多列b树索引(这正是KEY语法隐式创建的).