PostgreSQL繼承詳解

來源:互聯網
上載者:User

標籤:

PostgreSQL實現了表繼承,這個特性對資料庫設計人員來說是一個很有效工具。SQL99 及以後的標準定義了類型繼承特性,和我們在這裡描述的很多特性有區別。

讓我們從一個例子開始:假設我們試圖製作一個城市資料模型。每個州都有許多城市,但是只有一個首府。我們希望能夠迅速檢索任何州的首府。這個任務可以通過建立兩個表來實現,一個是州府表,一個是非州府表。不過,如果我們不管什麼城市都想查該怎麼辦? 繼承的特性可以協助我們解決這個問題。我們定義capitals表,它繼承自cities表:

CREATE TABLE cities (    name            text,    population      float,    altitude        int     -- 英尺); CREATE TABLE capitals (    state           char(2)) INHERITS (cities);

在這種情況下,capitals表繼承它的父表cities 中的所有屬性。州首府有一個額外的state屬性顯示其所在的州。

在PostgreSQL裡,一個表可以從零個或多個其它表中繼承屬性,而且一個查詢既可以引用一個表中的所有行,也可以引用一個表及其所有後代表的行(後面這個是預設行為)。比如,下面的查詢尋找所有海拔 500 英尺以上的城市名,包括州首府:

SELECT name, altitude    FROM cities    WHERE altitude > 500;

使用PostgreSQL教程裡面的資料,它返回:

   name    | altitude-----------+---------- Las Vegas |     2174 Mariposa  |     1953 Madison   |      845

另一方面,如果要找出不包括州首府的所有海拔超過 500 英尺的城市,查詢應該是這樣的:

SELECT name, altitude    FROM ONLY cities    WHERE altitude > 500;   name    | altitude-----------+---------- Las Vegas |     2174 Mariposa  |     1953

cities前面的ONLY表明該查詢應該只針對cities 而不包括其後代。許多我們已經討論過的命令(SELECT, UPDATE 和 DELETE)都支援ONLY關鍵字。

你也可以在表名後面寫一個*顯示指定包括所有後代表:

SELECT name, altitude    FROM cities*    WHERE altitude > 500;

因為這個行為是預設的,所以寫*並不是必須的(除非你已經改變了 sql_inheritance裡面的配置選項)。然而,寫* 可以用於強調搜尋額外的表。

有時候你可能想知道某個行版本來自哪個表。在每個表裡我們都有一個tableoid 系統屬性可以告訴你源表是誰:

SELECT c.tableoid, c.name, c.altitudeFROM cities cWHERE c.altitude > 500;

結果如下(你可能會得到不同的 OID):

 tableoid |   name    | altitude----------+-----------+----------   139793 | Las Vegas |     2174   139793 | Mariposa  |     1953   139798 | Madison   |      845

通過和pg_class做一個串連,就可以看到實際的表名字:

SELECT p.relname, c.name, c.altitudeFROM cities c, pg_class pWHERE c.altitude > 500 AND c.tableoid = p.oid;

它返回:

 relname  |   name    | altitude----------+-----------+---------- cities   | Las Vegas |     2174 cities   | Mariposa  |     1953 capitals | Madison   |      845

對於INSERT或COPY,繼承並不自動影響其後代表。在我們的例子裡,下面的INSERT語句將會失敗:

INSERT INTO cities (name, population, altitude, state)VALUES (‘New York‘, NULL, NULL, ‘NY‘);

我們可能希望資料被傳遞到capitals表裡面去,但這是不會發生的:INSERT總是插入明確聲明的那個表。在某些情況下,我們可以使用規則進行重新導向插入。不過它不能對上面的例子有什麼協助,因為cities表並不包含state 欄位,因此命令在規則施加之前就會被拒絕掉。

所有父表的檢查約束和非空約束都會自動被所有子表繼承。不過其它類型的約束(唯一、主鍵、外鍵約束)不會被繼承。

一個子表可以從多個父表繼承,這種情況下它將擁有所有父表欄位的總和,並且子表中定義的欄位也會加入其中。如果同一個欄位名出現在多個父表中,或者同時出現在父表和子表的定義裡,那麼這些欄位就會被"融合",這樣在子表裡就只有一個這樣的欄位。要想融合,欄位的資料類型必須相同,否則就會拋出一個錯誤。融合的欄位將會擁有其父欄位的所有檢查約束,並且如果某個父欄位存在非空約束,那麼融合後的欄位也必須是非空的。

表繼承通常使用帶INHERITS子句的CREATE TABLE語句定義。另外,一個已經用此方法定義的子表可以使用帶INHERIT的ALTER TABLE 命令添加一個新父表。注意:該子表必須已經包含新父表的所有欄位且類型一致,此外新父表的每個約束的名字及其運算式都必須包含在此子表中。同樣,一個繼承鏈可以使用帶NO INHERIT的ALTER TABLE命令從子表上刪除。允許動態添加和刪除繼承鏈對基於繼承關係的表分區很有用。

建立一個將要作為子表的新表的便利途徑是使用帶LIKE子句的 CREATE TABLE命令。它將建立一個與源表欄位相同的新表。如果源表中存在約束,那麼應該指定LIKE的INCLUDING CONSTRAINTS 選項,因為子表必須包含源表中的CHECK約束。

任何存在子表的父表都不能被刪除,同樣,子表中任何從父表繼承的欄位或約束也不能被刪除或修改。如果你想刪除一個表及其所有後代,最簡單的辦法是使用CASCADE選項刪除父表。

ALTER TABLE會把所有資料定義和檢查約束傳播到後代裡面去。另外,只有在使用CASCADE選項的情況下,才能刪除依賴於其他表的欄位。 ALTER TABLE在重複欄位融合和拒絕方面和CREATE TABLE的規則相同。

請注意表存取權限是如何處理的。訪問父表會自動訪問在子表中的資料,而不需要更多的存取權限檢查。這保留了父表中資料的表現。然而,直接存取子表不會自動允許訪問父表,要訪問父表需要更進一步的許可權被授予。

警告

注意,不是所有的 SQL 命令可以在所有的繼承層次上正常工作。資料查詢,資料修改,模式修改的命令(比如SELECT,UPDATE,DELETE, ALTER TABLE的大多數變型,但不是INSERT和 ALTER TABLE ... RENAME)典型的預設包括子表和支援ONLY符號來排除它們。為資料庫維護和調優的命令(例如REINDEX,VACUUM)通常只對個別工作,物理表格不支援遞迴超過繼承階層。單獨命令各自的行為記錄在了它們的參考頁中。

繼承的一個嚴重局限性是索引(包括唯一約束)和外鍵約束只能用於單個表,而不能包括它們的子表(不管對外鍵約束的參考資料表還是被參考資料表都是如此),因此,在上面的例子裡:

  • 即使我們聲明cities.name為UNIQUE或PRIMARY KEY,也不會阻止capitals表擁有重複名字的cities資料行。並且這些重複的行在查詢cities表的時候會顯示出來。實際上,預設時capitals將完全沒有唯一約束,因此可能包含帶有同名的多個行。你應該給capitals增加唯一約束,但即使這樣做也不能避免與cities的重複。

  • 類似的,即使我們聲明cities.name 參照(REFERENCES)某些其它的表,這個約束也不會自動傳播到capitals表。在這種條件下,你可以通過手工給capitals表增加同樣的REFERENCES約束來做到這點。

  • 聲明一個其它表的欄位為REFERENCES cities(name)將允許其它表包含城市名,但是不包含首府名。這種情況下沒有很好的繞開辦法。

這些缺點很可能在將來的版本中修補,但同時你也需要考慮一下,繼承是否對你的應用真正有用。

PostgreSQL繼承詳解

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.