PostgreSQL
 sql >> Base de Dados >  >> RDS >> PostgreSQL

Índice de várias colunas exclusivo do Postgres para tabela de junção

Como chave primária


Faça isso se esse exclusivo for a chave primária:
create table tbl(
   a_id int not null,
   b_id int not null,
   constraint tbl_pkey primary key(a_id,b_id)
);

Não é chave primária


Faça isso se esse exclusivo for uma chave não primária:
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)
);

Tabela existente


Se você tiver uma tabela existente, faça isso:
alter table tbl
      add constraint tbl_unique unique(a_id, b_id)

Essa tabela alter exibe esta mensagem:
NOTICE:  ALTER TABLE / ADD UNIQUE will create implicit index "tbl_unique" for table "tbl"


Query returned successfully with no result in 22 ms.

Descartar


Se você quiser eliminar essa restrição (você pode querer tornar única uma combinação de 3 campos):
ALTER TABLE tbl DROP CONSTRAINT tbl_unique;

Índice e restrição e nulos


Em relação ao índice, do documento do Postgres:

Fonte:http://www.postgresql.org/docs/9.1 /static/indexes-unique.html

Se a exclusividade depende de algumas regras, você deve usar CREATE UNIQUE INDEX , por exemplo:

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

alter table tbl
    add constraint tbl_unique unique(a_id, b_id);

Esse único pode pegar essas duplicatas, isso será rejeitado pelo banco de dados:
insert into tbl values
(1,1),
(1,1);

No entanto, essa UNIQUE CONSTRAINT não pode capturar nulos duplicados. Nulls serve como desconhecido, serve como curinga, é por isso que é permitido ter vários nulos em restrição exclusiva. Isso será aceito pelo banco de dados:
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

Pense em UNIQUE CONSTRAINT que permite exclusividade diferida, daí a aceitação de valores nulos acima.

Se você quiser apenas um curinga (null b_id) por a_id, além da restrição exclusiva, você precisa adicionar um UNIQUE INDEX . UNIQUE CONSTRAINT não pode ter uma expressão neles. INDEX e UNIQUE INDEX posso. Este será seu DDL completo para rejeitar múltiplos nulos;

Este será o seu DDL completo:
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;      

Isso será rejeitado pelo seu banco de dados agora:
insert into tbl values
(1,1),
(1,null),
(1,null);

Isso será permitido:
insert into tbl values
(1,1),
(1,null);

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