<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                ThinkChat2.0新版上線,更智能更精彩,支持會話、畫圖、視頻、閱讀、搜索等,送10W Token,即刻開啟你的AI之旅 廣告
                # 5.8\. 繼承 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教程里面的數據(參閱[Section 2.1](#calibre_link-1351)),它返回: ``` 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](#calibre_link-2218)里面的配置選項)。然而,寫`*` 可以用于強調搜索額外的表。 有時候你可能想知道某個行版本來自哪個表。在每個表里我們都有一個`tableoid` 系統屬性可以告訴你源表是誰: ``` SELECT c.tableoid, c.name, c.altitude FROM cities c WHERE 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.altitude FROM cities c, pg_class p WHERE 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`總是插入明確聲明的那個表。 在某些情況下,我們可以使用規則進行重定向插入(參閱 [Chapter 38](#calibre_link-472))。 不過它不能對上面的例子有什么幫助,因為`cities`表并不包含`state` 字段,因此命令在規則施加之前就會被拒絕掉。 所有父表的檢查約束和非空約束都會自動被所有子表繼承。 不過其它類型的約束(唯一、主鍵、外鍵約束)不會被繼承。 一個子表可以從多個父表繼承,這種情況下它將擁有所有父表字段的總和, 并且子表中定義的字段也會加入其中。如果同一個字段名出現在多個父表中, 或者同時出現在父表和子表的定義里,那么這些字段就會被"融合", 這樣在子表里就只有一個這樣的字段。要想融合,字段的數據類型必須相同, 否則就會拋出一個錯誤。融合的字段將會擁有其父字段的所有檢查約束, 并且如果某個父字段存在非空約束,那么融合后的字段也必須是非空的。 表繼承通常使用帶`INHERITS`子句的[CREATE TABLE](#calibre_link-7)語句定義。 另外,一個已經用此方法定義的子表可以使用帶`INHERIT`的[ALTER TABLE](#calibre_link-88) 命令添加一個新父表。注意:該子表必須已經包含新父表的所有字段且類型一致, 此外新父表的每個約束的名字及其表達式都必須包含在此子表中。同樣, 一個繼承鏈可以使用帶`NO INHERIT`的`ALTER TABLE`命令從子表上刪除。 允許動態添加和刪除繼承鏈對基于繼承關系的表分區(參見[Section 5.9](#calibre_link-1797))很有用。 創建一個將要作為子表的新表的便利途徑是使用帶`LIKE`子句的 `CREATE TABLE`命令。它將創建一個與源表字段相同的新表。 如果源表中存在約束,那么應該指定`LIKE`的`INCLUDING CONSTRAINTS` 選項,因為子表必須包含源表中的`CHECK`約束。 任何存在子表的父表都不能被刪除,同樣,子表中任何從父表繼承的字段或約束也不能被刪除或修改。 如果你想刪除一個表及其所有后代,最簡單的辦法是使用`CASCADE`選項刪除父表。 [ALTER TABLE](#calibre_link-88)會把所有數據定義和檢查約束傳播到后代里面去。另外, 只有在使用`CASCADE`選項的情況下,才能刪除依賴于其他表的字段。 `ALTER TABLE`在重復字段融合和拒絕方面和`CREATE TABLE`的規則相同。 請注意表訪問權限是如何處理的。訪問父表會自動訪問在子表中的數據,而不需要更多的訪問權限檢查。 這保留了父表中數據的表現。然而,直接訪問子表不會自動允許訪問父表,要訪問父表需要更進一步的權限被授予。 ## 5.8.1\. 警告 注意,不是所有的 SQL 命令可以在所有的繼承層次上正常工作。數據查詢,數據修改, 模式修改的命令(比如`SELECT`,`UPDATE`,`DELETE`, `ALTER TABLE`的大多數變型,但不是`INSERT`和 `ALTER TABLE ... RENAME`)典型的默認包括子表和支持`ONLY`符號來排除它們。 為數據庫維護和調優的命令(例如`REINDEX`,`VACUUM`) 通常只對個別工作,物理表格不支持遞歸超過繼承層次結構。單獨命令各自的行為記錄在了它們的參考頁中([Reference I, _SQL 命令_](#calibre_link-3))。 繼承的一個嚴重局限性是索引(包括唯一約束)和外鍵約束只能用于單個表, 而不能包括它們的子表(不管對外鍵約束的引用表還是被引用表都是如此),因此,在上面的例子里: * 即使我們聲明`cities`.`name`為`UNIQUE`或`PRIMARY KEY`, 也不會阻止`capitals`表擁有重復名字的`cities`數據行。 并且這些重復的行在查詢`cities`表的時候會顯示出來。實際上, 缺省時`capitals`將完全沒有唯一約束,因此可能包含帶有同名的多個行。 你應該給`capitals`增加唯一約束,但即使這樣做也不能避免與`cities`的重復。 * 類似的,即使我們聲明`cities`.`name` 參照(`REFERENCES`) 某些其它的表,這個約束也不會自動傳播到`capitals`表。在這種條件下, 你可以通過手工給`capitals`表增加同樣的`REFERENCES`約束來做到這點。 * 聲明一個其它表的字段為`REFERENCES cities(name)`將允許其它表包含城市名, 但是不包含首府名。這種情況下沒有很好的繞開辦法。 這些缺點很可能在將來的版本中修補,但同時你也需要考慮一下,繼承是否對你的應用真正有用。
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看