Postgres: Como fazer chaves compostas?

111

Não consigo entender o erro de sintaxe ao criar uma chave composta. Pode ser um erro lógico, porque testei muitas variedades.

Como você cria chaves compostas no Postgres?

CREATE TABLE tags
     (
              (question_id, tag_id) NOT NULL,
              question_id INTEGER NOT NULL,
              tag_id SERIAL NOT NULL,
              tag1 VARCHAR(20),
              tag2 VARCHAR(20),
              tag3 VARCHAR(20),
              PRIMARY KEY(question_id, tag_id),
              CONSTRAINT no_duplicate_tag UNIQUE (question_id, tag_id)
     );
    ERROR:  syntax error at or near "("
    LINE 3:               (question_id, tag_id) NOT NULL,
                          ^
Léo Léopold Hertz 준영
fonte

Respostas:

171

Sua PRIMARY KEYespecificação de composto já faz o que você deseja. Omita a linha que está apresentando um erro de sintaxe e omita também o redundante CONSTRAINT(já implícito):

 CREATE TABLE tags
      (
               question_id INTEGER NOT NULL,
               tag_id SERIAL NOT NULL,
               tag1 VARCHAR(20),
               tag2 VARCHAR(20),
               tag3 VARCHAR(20),
               PRIMARY KEY(question_id, tag_id)
      );

NOTICE:  CREATE TABLE will create implicit sequence "tags_tag_id_seq" for serial column "tags.tag_id"
    NOTICE:  CREATE TABLE / PRIMARY KEY will create implicit index "tags_pkey" for table "tags"
    CREATE TABLE
    pg=> \d tags
                                         Table "public.tags"
       Column    |         Type          |                       Modifiers       
    -------------+-----------------------+-------------------------------------------------------
     question_id | integer               | not null
     tag_id      | integer               | not null default nextval('tags_tag_id_seq'::regclass)
     tag1        | character varying(20) |
     tag2        | character varying(20) |
     tag3        | character varying(20) |
    Indexes:
        "tags_pkey" PRIMARY KEY, btree (question_id, tag_id)
pilcrow
fonte
Como você implementaria uma restrição como "CONSTRAINT no_duplicate_refences REFERÊNCIA UNIQUE FROM tag_id TO (tag1, tag2, tag3)"?
Léo Léopold Hertz 준영
4
@Masi, eu não acho que eu entendo o suficiente do que você está tentando modelar aqui, e, para ser franco, as colunas tag1através tag3sugerem-me que você pode ter refinamentos de design para fazer. Talvez uma pergunta separada, com uma descrição em linguagem natural de seu modelo e alguns registros de exemplo, ajude.
pilcrow de
18

O erro que você está recebendo está na linha 3. ou seja, não está em

CONSTRAINT no_duplicate_tag UNIQUE (question_id, tag_id)

mas antes:

CREATE TABLE tags
     (
              (question_id, tag_id) NOT NULL,

A definição correta da mesa é como a do pilcrow.

E se você deseja adicionar exclusivo em tag1, tag2, tag3 (o que parece muito suspeito), a sintaxe é:

CREATE TABLE tags (
    question_id INTEGER NOT NULL,
    tag_id SERIAL NOT NULL,
    tag1 VARCHAR(20),
    tag2 VARCHAR(20),
    tag3 VARCHAR(20),
    PRIMARY KEY(question_id, tag_id),
    UNIQUE (tag1, tag2, tag3)
);

ou, se você quiser que a restrição seja nomeada de acordo com seu desejo:

CREATE TABLE tags (
    question_id INTEGER NOT NULL,
    tag_id SERIAL NOT NULL,
    tag1 VARCHAR(20),
    tag2 VARCHAR(20),
    tag3 VARCHAR(20),
    PRIMARY KEY(question_id, tag_id),
    CONSTRAINT some_name UNIQUE (tag1, tag2, tag3)
);
Jon Bates
fonte