在PostgreSQL中是否可以让一个外键引用多个表?

jdzmm42g  于 2023-08-04  发布在  PostgreSQL
关注(0)|答案(1)|浏览(139)

我正在设计一个票务管理系统的数据库模式。架构的一部分将包括以下表:

CREATE TABLE workflow 
(
    workflow_id BIGINT GENERATED ALWAYS AS IDENTITY PRIMARY KEY
    -- other columns omitted for brevity
);

CREATE TABLE ticket_state 
(
    workflow_id BIGINT NOT NULL 
        REFERENCES workflow(workflow_id) ON DELETE CASCADE ON UPDATE CASCADE,
    ticket_state_ordinal INT NOT NULL,
    -- other columns omitted for brevity
    PRIMARY KEY (workflow_id, ticket_state_ordinal)
);

CREATE TABLE project 
(
    project_id BIGINT GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
    workflow_id BIGINT NOT NULL 
        REFERENCES workflow(workflow_id) ON UPDATE CASCADE
    -- other columns omitted for brevity
);

CREATE TABLE ticket 
(
    project_id BIGINT NOT NULL 
        REFERENCES project(project_id) ON DELETE CASCADE ON UPDATE CASCADE,
    ticket_id BIGINT NOT NULL,
    ticket_state_ordinal INT NOT NULL,
    -- other columns omitted for brevity
    PRIMARY KEY (project_id, ticket_id)
);

字符串
是否可以添加一个约束,将ticket.ticket_state_ordinal限制为与ticket.project_id引用的项目相关联的workflow_idticket_state.ticket_state_ordinal值?
我尝试向ticket添加一个workflow_id列,如下所示:

CREATE TABLE ticket 
(
    project_id BIGINT NOT NULL,
    ticket_id BIGINT NOT NULL,
    workflow_id BIGINT NOT NULL, -- purely for relational consistency
    ticket_state_ordinal INT NOT NULL,
    -- other columns omitted for brevity
    FOREIGN KEY (project_id, workflow_id) 
        REFERENCES project(project_id, workflow_id) ON DELETE CASCADE ON UPDATE CASCADE,
    FOREIGN KEY (workflow_id, ticket_state_ordinal) 
        REFERENCES ticket_state(workflow_id, ticket_state_ordinal) ON UPDATE CASCADE,
    PRIMARY KEY (project_id, ticket_id)
);


以便添加应保持值有效的两个外键。
然而,由于workflow_id上没有唯一索引,这在第一个外键处失败。
我预计这会失败,但无论如何都想尝试一下,以防postgres识别出外键引用整个主键,因此任何额外的列都保证只有1个值可供选择。

axr492tv

axr492tv1#

向引用表添加相应约束
最好始终引用主键,因为主键已经是唯一的,但是如果需要,可以添加更多

CREATE TABLE workflow (
    workflow_id BIGINT GENERATED ALWAYS AS IDENTITY PRIMARY KEY
    -- other columns omitted for brevity
);

CREATE TABLE ticket_state (
    workflow_id BIGINT NOT NULL REFERENCES workflow(workflow_id) ON DELETE CASCADE ON UPDATE CASCADE,
    ticket_state_ordinal INT NOT NULL,
    -- other columns omitted for brevity
    PRIMARY KEY (workflow_id, ticket_state_ordinal)
);

CREATE TABLE project (
    project_id BIGINT GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
    workflow_id BIGINT NOT NULL REFERENCES workflow(workflow_id) ON UPDATE CASCADE
      , unique (workflow_id, project_id) 
    -- other columns omitted for brevity
);
CREATE TABLE
CREATE TABLE
CREATE TABLE
CREATE TABLE ticket (
    project_id BIGINT NOT NULL,
    ticket_id BIGINT NOT NULL,
    workflow_id BIGINT NOT NULL, -- purely for relational consistency
    ticket_state_ordinal INT NOT NULL,
    -- other columns omitted for brevity
    FOREIGN KEY (project_id, workflow_id) REFERENCES project(project_id, workflow_id) ON DELETE CASCADE ON UPDATE CASCADE,
    FOREIGN KEY (workflow_id, ticket_state_ordinal) REFERENCES ticket_state(workflow_id, ticket_state_ordinal) ON UPDATE CASCADE,
    PRIMARY KEY (project_id, ticket_id)
);
CREATE TABLE

fiddle

相关问题