PostgreSQL foreign key constraint violation with i

2019-08-23 03:15发布

I have a PostgreSQL database, 3 tables and my schema as follows

--- 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)
);

Then i insert records in to both Parent and Child tables .

Parent

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

child

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

When I try to insert record into detail table following two entires was success

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

but I cant insert entry with record_id 3 it gave me a foreign key violation error

Can someone explain this error ??

Can we create foreign key relationship like this in Postgresql with inheritance

2条回答
兄弟一词,经得起流年.
2楼-- · 2019-08-23 03:49

No, that won't work.

Like the documentation says:

A serious limitation of the inheritance feature is that indexes (including unique constraints) and foreign key constraints only apply to single tables, not to their inheritance children. This is true on both the referencing and referenced sides of a foreign key constraint.

“Global indexes” are one of the important missing features of table inheritance.

查看更多
Ridiculous、
3楼-- · 2019-08-23 03:51

Sorry for the late answer. As the other answer states, Constraints are not inherited, so in your case parent has a primary key on record_id, but the child table does not have the same constraint. Without a primary key, a foreign key cannot point to it.

This is easily be fixed though by adding a primary key constraint to the child table also. The structure below would work fine:

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
);

This will work perfectly and allow child records to be referenced in the detail table. Note that I also added a primary to to the detail table, as good practice (although it did not contribute to answering your question).

The interesting thing about this, is that you are creating a constraint on column that is not mentioned anywhere in the CREATE TABLE statement. This is the nature of inheriting columns, but might not be obvious at first.

As of version 10 of PostgresSQL, constraint inheritance is not supported, so constraints (Unique, primary keys, foreign keys etc) must be recreated on child tables. I hope they fix this issue soon.

查看更多
登录 后发表回答