Postgres: Comment faire des clés composites?

112

Je ne comprends pas l'erreur de syntaxe lors de la création d'une clé composite. Cela peut être une erreur de logique, car j'ai testé de nombreuses variétés.

Comment créer des clés composites dans 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 준영
la source

Réponses:

172

Votre PRIMARY KEYspécification composée fait déjà ce que vous voulez. Omettez la ligne qui vous donne une erreur de syntaxe, et omettez également la redondante CONSTRAINT(déjà implicite):

 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
la source
Comment implémenteriez-vous une contraint comme "CONSTRAINT no_duplicate_refences UNIQUE REFERENCE FROM tag_id TO (tag1, tag2, tag3)"?
Léo Léopold Hertz 준영
4
@Masi, je ne pense pas que je comprends assez de ce que vous essayez de modèle ici, et, pour être franc, les colonnes tag1par tag3me portent à croire que vous pourriez avoir d'améliorations de conception à faire. Peut-être qu'une question distincte, avec une description en langage naturel de votre modèle et quelques exemples d'enregistrements, serait utile.
Pilcrow
18

L'erreur que vous obtenez est à la ligne 3. c'est-à-dire qu'elle n'est pas

CONSTRAINT no_duplicate_tag UNIQUE (question_id, tag_id)

mais plus tôt:

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

La définition correcte de la table est comme le montre le pilcrow.

Et si vous souhaitez ajouter des éléments uniques sur tag1, tag2, tag3 (ce qui semble très suspect), la syntaxe est la suivante:

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, si vous souhaitez que la contrainte soit nommée selon votre souhait:

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
la source