Thread: Inheritance in PostgreSQL
Hello, I'm in the process of developing a basic database structure that utilizes inheritance as part of a test for my work. The database consists of two tables: ‘PERSON' and ‘CUSTOMER' with the ‘PERSON' table serving as the parent table for ‘CUSTOMER' .
Initially, I defined the 'CREATE TABLE' statement as follows:
CREATE TABLE PERSON ( |
With these ‘INSERTS’, we have three records, as expected:
The problem occurs when we try add the ‘Fulano’ as a customer:
INSERT INTO CUSTOMER (id, name, dob, registration_date, contact) |
The 'CUSTOMER' table look like this:
However, this issue arises in the 'PERSON' table:
The primary key is duplicated when I attempted to add 'Fulano' as a customer.
After that, I attempted a slightly different approach in creating the ‘CUSTOMER’ table, as I'll show below:
CREATE TABLE customer ( |
But, when I run the same ‘INSERTS’ above, the same problem occurs with the ‘PERSON’ table:
I would like to know where I might be going wrong with these simple queries, and reinforce that my main question is: how to create a record for a ‘CUSTOMER’ who already exists in the ‘PERSON’ table?
A question that arose was to see that in the 'PERSON' table, there was a duplication of the record with the same 'id', considering that 'id' is a primary key.
I'm particularly interested in the advantages of the inheritance concept in PostgreSQL, considering that it can be easily applied to my business rules. I'd also like to know if inheritance is commonly used. Any insights and recommendations would be appreciated. Thank you.
My environment:
Oracle Linux Server 8.8
Postgres 15.4
This test was also performed in this environment:
Windows 10 Pro
Postgres 16
I'm particularly interested in the advantages of the inheritance concept in PostgreSQL
Hello, I'm in the process of developing a basic database structure that utilizes inheritance as part of a test for my work. The database consists of two tables: ‘PERSON' and ‘CUSTOMER' with the ‘PERSON' table serving as the parent table for ‘CUSTOMER' .
Initially, I defined the 'CREATE TABLE' statement as follows:
CREATE TABLE PERSON (
id SERIAL PRIMARY KEY,
name VARCHAR(255) NOT NULL,
dob DATE
);
CREATE TABLE CUSTOMER (
registration_date DATE NOT NULL,
contact VARCHAR(255)
) INHERITS (person);
INSERT INTO PERSON VALUES (1, 'Fulano', '1965-06-07');
INSERT INTO CUSTOMER VALUES (2, 'Beltrano', '1980-10-07', '2023-10-10', '5561999999999');With these ‘INSERTS’, we have three records, as expected:
The problem occurs when we try add the ‘Fulano’ as a customer:
INSERT INTO CUSTOMER (id, name, dob, registration_date, contact)
SELECT id, name, dob, '2023-10-17', 'contact@example.com'
FROM person
WHERE id = 1;The 'CUSTOMER' table look like this:
However, this issue arises in the 'PERSON' table:
The primary key is duplicated when I attempted to add 'Fulano' as a customer.
After that, I attempted a slightly different approach in creating the ‘CUSTOMER’ table, as I'll show below:
CREATE TABLE customer (
"id" int4 NOT NULL PRIMARY KEY DEFAULT nextval('person_id_seq'::regclass),
name VARCHAR(255) NOT NULL,
dob DATE,
registration_date DATE,
contact varchar(255)
) INHERITS (person);But, when I run the same ‘INSERTS’ above, the same problem occurs with the ‘PERSON’ table:
I would like to know where I might be going wrong with these simple queries, and reinforce that my main question is: how to create a record for a ‘CUSTOMER’ who already exists in the ‘PERSON’ table?
A question that arose was to see that in the 'PERSON' table, there was a duplication of the record with the same 'id', considering that 'id' is a primary key.
I'm particularly interested in the advantages of the inheritance concept in PostgreSQL, considering that it can be easily applied to my business rules. I'd also like to know if inheritance is commonly used. Any insights and recommendations would be appreciated. Thank you.
Data Normalization was "invented" to eliminate this problem (and many others).
CREATE TABLE person (
id BIGINT PRIMARY KEY GENERATED ALWAYS AS IDENTITY,
name TEXT,
dob DATE );
CREATE TABLE customer (
id BIGINT PRIMARY KEY GENERATED ALWAYS AS IDENTITY,
person_id BIGINT REFERENCES person(id),
registration_date DATE NOT NULL,
contact_info TEXT);
foo=# INSERT INTO person (name, dob) VALUES ('Fulano', '1965-06-07')
foo-# RETURNING id;
id
----
1
(1 row)
INSERT 0 1
foo=#
foo=# INSERT INTO customer (person_id, registration_date, contact_info)
foo-# values (1, '2023-10-10', '867-5309');
INSERT 0 1
foo=#
foo=# INSERT INTO person (name, dob) VALUES ('Beltrano', '1980-10-07')
RETURNING id;
id
----
2
(1 row)
INSERT 0 1
foo=#
foo=# INSERT INTO customer (person_id, registration_date, contact_info)
values (2, '2023-10-12', '555-1212');
INSERT 0 1
foo=#
foo=# SELECT p.*, c.*
foo-# FROM person p, customer c
foo-# WHERE p.id = c.person_id;
id | name | dob | id | person_id | registration_date | contact_info
----+----------+------------+----+-----------+-------------------+--------------
1 | Fulano | 1965-06-07 | 1 | 1 | 2023-10-10 | 867-5309
2 | Beltrano | 1980-10-07 | 2 | 2 | 2023-10-12 | 555-1212
(2 rows)
foo=# INSERT INTO customer (person_id, registration_date, contact_info)
values (8, '2023-09-11', '(212)555-1212');
ERROR: insert or update on table "customer" violates foreign key constraint "customer_person_id_fkey"
DETAIL: Key (person_id)=(8) is not present in table "person".
Born in Arizona, moved to Babylonia.
“Don’t use table inheritance” IS on that page
From: David G. Johnston <david.g.johnston@gmail.com>
Also of note:
I'm tempted to add "Don't use inheritance" to that page...but fortunately it doesn't come up that often.
David J.
“Don’t use table inheritance” IS on that page
“Don’t use table inheritance” IS on that page
Thank you all for your responses. I appreciate the input on the use of table inheritance in PostgreSQL, and I will take your recommendations into consideration. The provided link is also quite useful, and I'm grateful for the solution provided by Ron regarding normalization. Thanks!
Merlin Moncure schrieb am 18.10.2023 um 03:20: > The only thing you can't really do in SQL easily without writing > nasty triggers are things like, 'this table must be linked from one > and only one of these candidate tables'. I think the language > probably ought to support this, but I don't think postgres would > unless the standard did. Isn't that what assertions are intended to solve in the SQL standard?
Merlin Moncure schrieb am 18.10.2023 um 03:20:
> The only thing you can't really do in SQL easily without writing
> nasty triggers are things like, 'this table must be linked from one
> and only one of these candidate tables'. I think the language
> probably ought to support this, but I don't think postgres would
> unless the standard did.
Isn't that what assertions are intended to solve in the SQL standard?