您好,登錄后才能下訂單哦!
這篇文章主要介紹“怎么理解PostgreSQL表繼承”,在日常操作中,相信很多人在怎么理解PostgreSQL表繼承問題上存在疑惑,小編查閱了各式資料,整理出簡單好用的操作方法,希望對大家解答”怎么理解PostgreSQL表繼承”的疑惑有所幫助!接下來,請跟著小編一起來學習吧!
PostgreSQL實現了表繼承,這對數據庫設計者來說是一種有用的工具(SQL:1999及其后的版本定義了一種類型繼承特性,但和這里介紹的繼承有很大的不同)。讓我們從一個例子開始:假設我們要為城市建立一個數據模型。每一個州有很多城市,但是只有一個首府。我們希望能夠快速地檢索任何特定州的首府城市。這可以通過創建兩個表來實現:一個用于州首府,另一個用于不是首府的城市。然而,當我們想要查看一個城市的數據(不管它是不是一個首府)時會發生什么?繼承特性將有助于解決這個問題。我們可以將capitals表定義為繼承自cities表:
jydb=# CREATE TABLE cities ( jydb(# name text, jydb(# population float, jydb(# altitude int -- in feet jydb(# ); CREATE TABLE jydb=# CREATE TABLE capitals ( jydb(# state char(2) jydb(# ) INHERITS (cities); CREATE TABLE jydb=# insert into cities values('Las Vegas',600,2174); INSERT 0 1 jydb=# insert into cities values('Mariposa',500,1953); INSERT 0 1 jydb=# insert into cities values('Madison',450,845); INSERT 0 1 jydb=# insert into capitals values('Houston',400,745,'LA'); INSERT 0 1 jydb=# select * from cities; name | population | altitude -----------+------------+---------- Las Vegas | 600 | 2174 Mariposa | 500 | 1953 Madison | 450 | 845 Houston | 400 | 745 (4 rows) jydb=# select * from capitals; name | population | altitude | state ---------+------------+----------+------- Houston | 400 | 745 | LA (1 row)
在這種情況下,capitals表繼承了它父表cities的所有列。州首府還有一個額外的列state用來表示它所屬的州。
在PostgreSQL中,一個表可以從0個或者多個其他表繼承,而對一個表的查詢則可以引用一個表的所有行或者該表的所有行加上它所有的后代表。默認情況是后一種行為。例如,下面的查詢將查找所有海拔高于500尺的城市的名稱,包括州首府:
jydb=# SELECT name, altitude FROM cities WHERE altitude > 500; name | altitude -----------+---------- Las Vegas | 2174 Mariposa | 1953 Madison | 845 Houston | 745 (4 rows)
在另一方面,下面的查詢將找到海拔超過500尺且不是州首府的所有城市:
jydb=# SELECT name, altitude FROM ONLY cities WHERE altitude > 500; name | altitude -----------+---------- Las Vegas | 2174 Mariposa | 1953 Madison | 845 (3 rows)
這里的ONLY關鍵詞指示查詢只被應用于cities上,而其他在繼承層次中位于cities之下的其他表都不會被該查詢涉及。很多我們已經討論過的命令(如SELECT、UPDATE和DELETE)都支持ONLY關鍵詞。
我們也可以在表名后寫上一個*來顯式地將后代表包括在查詢范圍內:
jydb=# SELECT name, altitude FROM cities* WHERE altitude > 500; name | altitude -----------+---------- Las Vegas | 2174 Mariposa | 1953 Madison | 845 Houston | 745 (4 rows)
*并不是必須的,因為它對應的行為是默認的(除非改變sql_inheritance配置選項的設置)。但是書寫*有助于強調會有附加表被搜索。
在某些情況下,我們可能希望知道一個特定行來自于哪個表。每個表中的系統列tableoid可以告訴我們行來自于哪個表:
jydb=# SELECT c.tableoid, c.name, c.altitude FROM cities c WHERE c.altitude > 500; tableoid | name | altitude ----------+-----------+---------- 24653 | Las Vegas | 2174 24653 | Mariposa | 1953 24653 | Madison | 845 24659 | Houston | 745 (4 rows)
(如果重新生成這個結果,可能會得到不同的OID數字。)通過與pg_class進行連接可以看到實際的表名:
jydb=# SELECT p.relname, c.name, c.altitude jydb-# FROM cities c, pg_class p jydb-# WHERE c.altitude > 500 AND c.tableoid = p.oid; relname | name | altitude ----------+-----------+---------- cities | Las Vegas | 2174 cities | Mariposa | 1953 cities | Madison | 845 capitals | Houston | 745 (4 rows)
另一種得到同樣效果的方法是使用regclass偽類型, 它將象征性地打印出表的 OID:
jydb=# SELECT c.tableoid::regclass, c.name, c.altitude jydb-# FROM cities c jydb-# WHERE c.altitude > 500; tableoid | name | altitude ----------+-----------+---------- cities | Las Vegas | 2174 cities | Mariposa | 1953 cities | Madison | 845 capitals | Houston | 745 (4 rows)
繼承不會自動地將來自INSERT或COPY命令的數據傳播到繼承層次中的其他表中。在我們的例子中,下面的INSERT語句將會失敗:
jydb=# INSERT INTO cities (name, population, altitude, state) VALUES (’Albany’, NULL, NULL, ’NY’); ERROR: column "state" of relation "cities" does not exist LINE 1: INSERT INTO cities (name, population, altitude, state) VALUE...
^
我們也許希望數據能被以某種方式被引入到capitals表中,但是這不會發生:INSERT總是向指定的表中插入。在某些情況下,可以通過使用一個規則(見第 39 章)來將插入動作重定向。但是這對上面的情況并沒有幫助,因為cities表根本就不包含state列,因而這個命令將在觸發規則之前就被拒絕。
父表上的所有檢查約束和非空約束都將自動被它的后代所繼承。其他類型的約束(唯一、主鍵和外鍵約束)則不會被繼承。
一個表可以從多個父表繼承,在這種情況下它擁有父表們所定義的列的并集。任何定義在子表上的列也會被加入到其中。如果在這個集合中出現重名列,那么這些列將被"合并",這樣在子表中只會有一個這樣的列。重名列能被合并的前提是這些列必須具有相同的數據類型,否則會導致錯誤。可繼承的檢查約束和非空約束以類似的方式合并。因此,例如,如果任何列定義被標記為not-null,則合并列將被標記為not-null。如果檢查約束具有相同的名稱,則合并它們;如果條件不同,則合并將失敗。
表繼承通常是在子表被創建時建立,使用CREATE TABLE語句的INHERITS子句。一個已經被創建的表也可以另外一種方式增加一個新的父親關系,使用ALTER TABLE的INHERIT變體。要這樣做,新的子表必須已經包括和父表相同名稱和數據類型的列。子表還必須包括和父表相同的檢查約束和檢查表達式。相似地,一個繼承鏈接也可以使用ALTER TABLE的 NO INHERIT變體從一個子表中移除。動態增加和移除繼承鏈接可以用于實現表劃分
一種創建一個未來將被用做子女的新表的方法是在CREATE TABLE中使用LIKE子句。這將創建一個和源表具有相同列的新表。如果源表上定義有任何CHECK約束,LIKE的INCLUDING CONSTRAINTS選項可以用來讓新的子表也包含和父表相同的約束。
當有任何一個子表存在時,父表不能被刪除。當子表的列或者檢查約束繼承于父表時,它們也不能被刪除或修改。如果希望移除一個表和它的所有后代,一種簡單的方法是使用CASCADE選項刪除父表
ALTER TABLE將會把列的數據定義或檢查約束上的任何變化沿著繼承層次向下傳播。同樣,刪除被其他表依賴的列只能使用CASCADE選項。ALTER TABLE對于重名列的合并和拒絕遵循與CREATE TABLE同樣的規則。
繼承查詢只對父表執行訪問權限檢查。因此,例如,對cities表授予update權限會意味著通過cities訪問capitals表時也能更新capitals表。這體現了子表中的數據也在父表中。但是capitals表在沒有額外地授權情況下不能被直接更新。以類似的方式,父表的行安全策略在執行繼承查詢時會應用到子表的行記錄。子表的策略(如果有的話)僅當它是查詢中顯式命名的表時才應用;在這種情況下,任何附加到其父級的策略都將被忽略。
外部表也可以是繼承層次 中的一部分,即可以作為父表也可以作為子表,就像常規表一樣。如果一個外部表是繼承層次的一部分,那么任何不被該外部表支持的操作也不被整個層次所支持。
到此,關于“怎么理解PostgreSQL表繼承”的學習就結束了,希望能夠解決大家的疑惑。理論與實踐的搭配能更好的幫助大家學習,快去試試吧!若想繼續學習更多相關知識,請繼續關注億速云網站,小編會繼續努力為大家帶來更多實用的文章!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。