【问题标题】:PostgreSQL foreign key constraint violation with inheritancePostgreSQL外键约束违反继承
【发布时间】:2017-03-11 04:37:51
【问题描述】:

我有一个 PostgreSQL 数据库、3 个表和我的架构如下

--- Parent Table

CREATE TABLE IF NOT EXISTS abc.parent(
    record_id         SERIAL PRIMARY KEY,
    description       text NOT NULL
);

--- Child Table


CREATE TABLE IF NOT EXISTS abc.child ( 
    total_count INT NOT NULL)  INHERITS (abc.parent);

-- Detail

CREATE TABLE abc.detail(
    detail_id      int NOT NULL,
    detail_description       text NOT NULL
    record_id         int NOT NULL,
    FOREIGN KEY (record_id) REFERENCES abc.parent(record_id)
);

然后我将记录插入到父表和子表中。

父母

|record_id|description|
|1        |abcd       |
|2        |efgh       |

孩子

|record_id|description|total_count|
|3        |xygh       |5          |
|4        |mnop       |7          |

当我尝试将记录插入到两个完整之后的详细表中时成功

Detail
|detail_id|detail_description|record_id|
|100      |detail_desc1      |  1      |
|200      |detail_desc2      |  2      |

但我无法插入带有 record_id 3 的条目,它给了我一个外键违规错误

谁能解释一下这个错误??

我们可以在Postgresql中用继承创建这样的外键关系

【问题讨论】:

    标签: sql postgresql foreign-keys


    【解决方案1】:

    抱歉回复晚了。正如其他答案所述,约束不是继承的,因此在您的情况下,父表在 record_id 上有一个主键,但子表没有相同的约束。没有主键,外键就不能指向它。

    这很容易通过向子表添加主键约束来解决。下面的结构可以正常工作:

    CREATE TABLE IF NOT EXISTS abc.parent
    (
        record_id         SERIAL,
        description       text NOT NULL,
        CONSTRAINT parent_pkey PRIMARY KEY (record_id)
    );
    
    --- Child Table
    
    CREATE TABLE IF NOT EXISTS abc.child 
    ( 
        total_count INT NOT NULL,
        CONSTRAINT child_pkey PRIMARY KEY (record_id)
    )  INHERITS (abc.parent);
    
    -- Detail
    
    CREATE TABLE abc.detail
    (
      detail_id integer NOT NULL,
      detail_description text NOT NULL,
      record_id integer NOT NULL,
      CONSTRAINT detail_pkey PRIMARY KEY (detail_id),
      CONSTRAINT detail_record_id_fkey FOREIGN KEY (record_id)
          REFERENCES abc.parent (record_id) MATCH SIMPLE
          ON UPDATE NO ACTION ON DELETE NO ACTION
    );
    

    这将完美地工作并允许在详细表中引用子记录。请注意,作为良好做法,我还向详细信息表添加了一个主要的(尽管它没有帮助回答您的问题)。

    有趣的是,您正在对 CREATE TABLE 语句中未提及的列创建约束。这是继承列的本质,但一开始可能并不明显。

    从 PostgresSQL 版本 10 开始,不支持约束继承,因此必须在子表上重新创建约束(唯一键、主键、外键等)。我希望他们能尽快解决这个问题。

    【讨论】:

    • 我已经运行了您的代码,然后执行了以下操作:INSERT INTO abc.child (description, total_count) VALUES('xpto', 0); INSERT INTO abc.detail (detail_id, detail_description, record_id) VALUES(0, '', 1); 但收到此错误消息:> SQL Error [23503]: ERROR: insert or update on table "detail" violates > foreign key constraint "detail_record_id_fkey" Detalhe: Key > (record_id)=(1) is not present in table "parent" 知道我做错了什么吗?我正在使用 Postgres 12。
    【解决方案2】:

    不,这行不通。

    就像the documentation 说的:

    继承特性的一个严重限制是索引 (包括唯一约束)和外键约束仅适用 到单个表,而不是它们的继承子表。这是真的 在外键约束的引用侧和被引用侧。

    “全局索引”是表继承的重要缺失特性之一。

    【讨论】:

      猜你喜欢
      • 2018-04-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-10-24
      相关资源
      最近更新 更多