Postgres FK, ссылающийся на композитный ПК

Рассмотрим

CREATE TABLE foo (
    id SERIAL,
    foo_created_on ABSTIME,
    foo_deactivated_on ABSTIME,
    PRIMARY KEY (id, foo_created_on)
);

CREATE TABLE bar (
    id SERIAL,
    bar_created_on ABSTIME,
    bar_deactivated_on ABSTIME,
    foo_id REFERENCES ( .. what goes here? ..),
    PRIMARY KEY (id, bar_created_on)
);

Как создать FK в "баре", который ссылается на PK в "foo"?

Ответ 1

Как создать FK в "баре", который ссылается на PK в "foo"?

С вашей текущей структурой вы не можете.

Цель ссылки внешнего ключа должна быть объявлена ​​либо PRIMARY KEY, либо UNIQUE. Таким образом, либо этот

CREATE TABLE foo (
    id SERIAL PRIMARY KEY,
    foo_created_on ABSTIME,
    foo_deactivated_on ABSTIME,
    UNIQUE (id, foo_created_on)
);

или

CREATE TABLE foo (
    id SERIAL,
    foo_created_on ABSTIME,
    foo_deactivated_on ABSTIME,
    PRIMARY KEY (id, foo_created_on),
    UNIQUE (id)
);

будет работать как объект для bar.foo_id. Тогда бар будет иметь простую ссылку.

CREATE TABLE bar (
    id SERIAL,
    bar_created_on ABSTIME,
    bar_deactivated_on ABSTIME,
    foo_id REFERENCES foo (id),
    PRIMARY KEY (id, bar_created_on)
);

Если вы хотите ссылаться на первичный ключ, который вы первоначально объявили в foo, вы должны сохранить этот первичный ключ в строке. Вы должны хранить все это, а не часть его. Таким образом, без изменения foo вы можете создать такой бар.

CREATE TABLE bar (
    id SERIAL,
    bar_created_on ABSTIME,
    bar_deactivated_on ABSTIME,
    foo_id INTEGER NOT NULL,
    foo_created_on ABSTIME NOT NULL,
    FOREIGN KEY (foo_id, foo_created_on) REFERENCES foo (foo_id, foo_created_on),
    PRIMARY KEY (id, bar_created_on)
);

Ответ 2

Вам нужно создать отдельные внешние ключи:

CREATE TABLE bar (
  id SERIAL,
  bar_created_on ABSTIME,
  bar_deactivated_on ABSTIME,
  foo_id INT,
  FOREIGN KEY (foo_id, created_on) REFERENCES foo (id, created_on),
  PRIMARY KEY (id, bar_created_on)
);