Postgres: ¿Cómo hacer claves compuestas?

111

No puedo entender el error de sintaxis al crear una clave compuesta. Puede ser un error de lógica, porque he probado muchas variedades.

¿Cómo se crean claves compuestas en 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 준영
fuente

Respuestas:

171

Su PRIMARY KEYespecificación compuesta ya hace lo que quiere. Omita la línea que le está dando un error de sintaxis y omita la redundante CONSTRAINT(ya implícita) también:

 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
fuente
¿Cómo implementaría una restricción como "CONSTRAINT no_duplicate_refences REFERENCIA ÚNICA DE tag_id TO (tag1, tag2, tag3)"?
Léo Léopold Hertz 준영
4
@Masi, no creo que entiendo bastante de lo que estamos tratando de modelar aquí, y, para ser franco, las columnas tag1a través de tag3me sugieren que es posible que tenga otras mejoras de diseño que hacer. Quizás una pregunta separada, con una descripción en lenguaje natural de su modelo y algunos registros de ejemplo, ayudaría.
Pilcrow
18

El error que está recibiendo está en la línea 3. es decir, no está en

CONSTRAINT no_duplicate_tag UNIQUE (question_id, tag_id)

pero antes:

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

La definición correcta de la tabla es como se muestra en Pilcrow.

Y si desea agregar único en tag1, tag2, tag3 (que suena muy sospechoso), entonces la sintaxis es:

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)
);

o, si desea que la restricción se nombre de acuerdo con su deseo:

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
fuente