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