PostgreSQL中的繼承

OnlyQi發表於2020-10-03

Inheritance是PostgreSQL獨有的,也是前文中我們提到的“使用物件導向的思想來組織資料庫”的具體體現之一。

一, 表的繼承。
這裡我們使用官網說明中的例子,原文在這裡:
https://www.postgresql.org/docs/12/tutorial-inheritance.html

CREATE TABLE cities (
name text,
population real,
elevation int – (in ft)
);
CREATE TABLE capitals (
state char(2)
) INHERITS (cities);

省會其實也是城市,只是比普通的城市多了一個state,表明是哪個省的省會。在上例中capitals表繼承了cities表中的所有欄位。In PostgreSQL, a table can inherit from zero or more other tables.

INSERT INTO cities VALUES (‘洛陽’,1500, 50);
INSERT INTO cities VALUES (‘開封’,1000, 50);
INSERT INTO capitals VALUES (‘鄭州’,2000, 50, ‘HN’);

假設有洛陽,鄭州和開封三個城市,其中鄭州是省會城市。由上面可見,插入資料時只需要向capitals插入鄭州的資料即可。根據物件導向的思想,我們可以認為表中的每一行就是一個例項化後的物件,而鄭州只應該被例項化一次。此時檢視錶中的資料:

SELECT * FROM cities;
“name” “population” “elevation”
“洛陽” “1500” “50”
“開封” “1000” “50”
“鄭州” “2000” “50”

SELECT * FROM capitals;
“name” “population” “elevation” “state”
“鄭州” “2000” “50” “HN”

檢視了資料後,我們可以很容易地理解下面的語句:

SELECT name, elevation
FROM ONLY cities;

上面的SQL返回除省會以外的所有城市。Here the ONLY before cities indicates that the query should be run over only the cities table, and not tables below cities in the inheritance hierarchy.
這裡有一個帖子討論使用table inheritation到底能帶來什麼益處:
https://stackoverflow.com/questions/3074535/when-to-use-inherited-tables-in-postgresql

二, Type的“繼承”

首先要說明的是,PostgreSQL並不支援type的繼承,這也是上面的繼承打上引號的原因。
資料型別是每個資料庫都有的概念,例如int32,char等等。PostgreSQL中的composite type很特別。本質上說,composite type is essentially just a list of field names and their data types.

CREATE TYPE inventory_item AS (
name text,
supplier_id integer,
price numeric
);
CREATE TABLE on_hand (
item inventory_item, – 使用剛剛定義的type
count integer
);
INSERT INTO on_hand VALUES (ROW(‘fuzzy dice’, 42, 1.99), 1000);
–注意這裡的ROW()是構造type的方法。

需要注意的是當建立一張表時,一個composite type就會自動建立出來,type名與表名相同,且使用方式和一般的type無異。我們也可以像下面這樣使用type建表:

CREATE TABLE on_hand2 OF inventory_item;

回到我們的問題,由於type沒有直接的繼承,因此在postgres中我們可以這樣實現變相的type繼承:

CREATE TYPE supertype AS (
foo int,
bar text
);
CREATE TYPE subtype AS (
super supertype,
baz int
);

三,如何查詢使用了type的表的資料:

SELECT item FROM on_hand;
“item”
“(”“fuzzy dice”",42,1.99)" – 返回的是一個type物件,因此需要用如下語句查詢column:

SELECT (item).name,(item).* FROM on_hand;
“name” “name” “supplier_id” “price”
“fuzzy dice” “fuzzy dice” “42” “1.99”

最後,由於PostgreSQL支援繼承,因此很多table,view等等形成了複雜的依賴關係。PostgreSQL提供方法來查詢這些依賴關係。
https://www.postgresql.org/docs/12/ddl-depend.html

相關文章