Foreign key matching in PostgreSQL

半城伤御伤魂 提交于 2019-12-13 01:16:01

问题


Just curious, if I have this table:

CREATE TABLE "post" (
    "id" SERIAL,
    "revision" INTEGER NOT NULL DEFAULT 0,
    "summary" CHARACTER VARYING NOT NULL,
    "description" TEXT NOT NULL,
    "user_id" INTEGER NOT NULL
        REFERENCES "user" ("id") MATCH FULL
            ON UPDATE CASCADE
            ON DELETE RESTRICT,
    "post_type_id" INTEGER NOT NULL
        REFERENCES "post_type" ("id") MATCH FULL
            ON UPDATE CASCADE
            ON DELETE RESTRICT,
    "ctime" TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
    PRIMARY KEY("id", "revision")
);

to store posts, and this table:

CREATE TABLE "post_state" (
    "post_id" INTEGER NOT NULL,
    "assembly_seat_id" INTEGER NOT NULL
        REFERENCES "assembly_seat" ("id") MATCH FULL
            ON UPDATE CASCADE
            ON DELETE RESTRICT,
    PRIMARY KEY("post_id")
);

and I want my post_id field to point to post(id), how do I do it? I have tried with the following phrase:

    "post_id" INTEGER NOT NULL UNIQUE,
        REFERENCES "post" ("id") MATCH SIMPLE
            ON UPDATE RESTRICT
            ON DELETE RESTRICT,

but I am getting this error:

ERROR: there is no unique constraint matching given keys for referenced table "post"

The values of post_state(asembly_seat_id) do not change in this case.


回答1:


A foreign key constraint can span multiple columns. You could just add the column revision to the table post_state.

CREATE TEMP TABLE post (
  post_id serial NOT NULL
 ,revision integer NOT NULL DEFAULT 0
 ,summary text NOT NULL
 ,description text NOT NULL
 ,user_id integer NOT NULL
    REFERENCES user (id) MATCH FULL ON UPDATE CASCADE ON DELETE RESTRICT
 ,post_type_id integer NOT NULL
    REFERENCES post_type (id) MATCH FULL ON UPDATE CASCADE ON DELETE RESTRICT
 ,ctime timestamptz DEFAULT NOW()
 ,PRIMARY KEY(post_id, revision)
);

CREATE TEMP TABLE post_state (
  post_id integer NOT NULL
 ,revision integer NOT NULL
 ,assembly_seat_id integer NOT NULL
    REFERENCES assembly_seat (id) MATCH FULL ON UPDATE CASCADE ON DELETE RESTRICT
 ,PRIMARY KEY(post_id, revision)
 ,FOREIGN KEY (post_id, revision) REFERENCES post (post_id, revision)
);

Read the manual about foreign key constraints.

I am using the name post_id for the primary key column of table post. Don't use id as column name. If you join a bunch of tables you end up with a bunch of columns all names id. Regrettably, some half-wit ORMs are in the habit of doing that.

Alternatively, it might be better design to have unique post_id in table post and add a table post_revision with a n:1 relation to post.



来源:https://stackoverflow.com/questions/16462098/foreign-key-matching-in-postgresql

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!