Chapter 33. 規則系統

Table of Contents
33.1. 查詢樹
33.2. 視圖和規則系統
33.2.1. SELECT規則如何運轉
33.2.2. SELECT語句的視圖規則
33.2.3. PostgreSQL裡視圖的強大能力
33.2.4. 更新一個視圖
33.3. INSERTUPDATE,和DELETE 上的規則
33.3.1. 更新規則是如何運轉的
33.3.2. 與視圖合作
33.4. 規則和權限
33.5. 規則和命令狀態
33.6. 規則與觸發器之比較

本章討論 PostgreSQL 裡的規則系統。 生產規則系統的概念是很簡單的,但是在實際使用的時候會碰到很多細微的問題。

有些其它的資料庫系統定義動態的資料庫規則。這些通常是儲存過程和觸發器, 在 PostgreSQL 裡,這些東西也可以透過函數和觸發器來實現。

規則系統,(更準確地說,查詢重寫規則系統)是和儲存過程和觸發器完全不同的東西。 它把查詢修改為需要考慮規則的形式,然後把修改過的查詢傳遞給查詢規劃器執行。 這是非常有效的工具並且可以用於許多象查詢語言過程,視圖,和版本等。 這個規則系統的理論基礎和能力在 有關資料庫系統的規則,過程,緩存和視圖A Unified Framework for Version Modeling Using Production Rules in a Database System 裡有討論。

33.1. 查詢樹

要理解規則系統如何工作,首先要知道規則何時被激發以及它的輸入和結果是什麼。

規則系統位於分析器和規劃器之間。以分析器的輸出 -- 一個查詢樹, 以及用戶定義的重寫規則作為輸入, 重寫規則也是一個查詢樹,只不過增加了一些擴展訊息, 然後建立零個或者多個查詢樹作為結果。 所以它的輸入和輸出仍然是那些分析器可以生成的東西, 因而任何它(規則系統)看到的東西都是可以用 SQL 語句資料表達的。

那麼什麼是查詢樹呢? 它是一個 SQL 語句的內部資料表現形式, 這時組成該語句的每個獨立地部分都是分別儲存的。 如果您設置了配置參數 debug_print_parsedebug_print_rewritten,或 debug_print_plan, 那麼您可以在伺服器日誌中看到這些查詢樹。 規則動作也是以查詢樹的方式儲存的,存放在系統資料表pg_rewirte 裡面。不過不是用象調試輸出那樣的格式,但包含的內容是完全一樣的。

閱讀一個裸查詢樹需要一定的經驗, 但是因為理解查詢樹的 SQL 資料表現就足以理解規則系統, 所以這份文件將不會告訴您如何讀取它們。

當我們讀取本章中查詢樹的 SQL 資料表現時, 我們必須能夠識別該語句被分解後放在查詢樹裡的成員。 查詢樹的成員有

命令類型 ( command type )

這是一個簡單的值,說明哪條命令 (SELECTINSERTUPDATEDELETE) 生成這個查詢樹。

範圍資料表 (range table)

範圍資料表是一個查詢中使用的關係的列資料表。 在SELECT語句裡是在FORM關鍵字後面給出的關係。

每個範圍資料表資料表示一個資料表或一個視圖,資料表明是查詢裡哪個成員調用了它。 在查詢樹裡,範圍資料表是用代號而不是用名字引用的, 所以這裡不用像在 SQL語句裡一樣關心是否有重名問題。 這種情況在引入了規則的範圍資料表後可能會發生。 本章的例子將不討論這種情況。

結果關係(result relation)

這是一個範圍資料表的索引,用於標識查詢結果前往的資料表。

SELECT查詢通常沒有結果關係資料表。特例SELECT INTO 幾乎等於一個 CREATE TABLEINSERT ... SELECT序列,所以這裡我們就不單獨討論了。

INSERTUPDATEDELETE命令裡, 結果關係是更改發生影響的資料表(或視圖!)。

目標列 (target list)

目標列是一列定義查詢結果的資料表達式。在SELECT的情況下, 這些資料表達式就是構建查詢的最終輸出的東西。 它們是位於SELECTFROM關鍵字之間的資料表達式 (* 只是資料表明一個關係的所有字串的縮寫,它被分析器擴展為獨立的字串, 因此規則系統永遠看不到它)。

DELETE 不需要目標列是因為它們不產生任何結果。 實際上規劃器會向空目的標列中增加一條特殊的CTID記錄。 但這是在規則系統之後並且我們將稍後討論;對於規則系統而言,目標列是空的。

對於INSERT命令裡面,目標列描述了應該進入結果關係的新行。 這些由那些在VALUES子句裡的資料表達式或在 INSERT ... SELECT 語句裡的 SELECT 子句裡面的資料表達式構成。 重寫過程的第一步就是為任何不是由原始的查詢賦值,並且有預設值的字串增加目標列資料表項。 任何其它的字串(既無給出值,也無預設的)將由規劃器自動賦予一個常量 NULL 資料表達式。

對於UPDATE命令,它(目標列)描述應該替換舊行的新行。 在規則系統裡,它只包含來自查詢的 SET attribute = expression部分抽取的資料表達式。 這時,規劃器將透過插入從舊行抽取資料到新行的資料表達式的方法處理缺失的字串。 並且它也會像 在DELETE裡那樣增加特殊的CTID記錄。

目標列裡的每個元素都包含著一個資料表達式, 它可以為常量值,可以為一個指向某個範圍資料表裡面的關係的一個字串的變量, 可以為一個由函數調用,常量,變量,操作符等構成的資料表達式樹。

條件 (qualification)

查詢條件是一個資料表達式,它非常類似那些包含在目標列裡的條目。 這個資料表達式的值是一個布爾值,透過此值來判斷對最終結果行是否要執操作 (INSERTUPDATEDELETESELECT)。 它是一個SQL 語句 的WHERE子句。

連接樹

查詢的連接樹顯示了FROM 子句的結構。 對於象SELECT FROM a, b, c這樣的簡單查詢, 連接樹只是一個FROM項的簡單列資料表, 因為我們允許以任意順序連接它們。 但如果使用了 JOIN 資料表達式 — 尤其是 outer join 的時候, 我們就必須按照該連接顯示的順序進行連接。 連接樹顯示 JOIN 資料表達式的結構。 與特定的 JOIN 子句(來自 ON 或者 USING 資料表達式)相關的限制做為附加在那些連接樹節點的條件資料表達式儲存。 事實證明把頂層 WHERE 資料表達式也當做附加在頂層連接樹項的條件來儲存是非常方便的。所以實際上連接樹代資料表SELECT語句的 FROMWHERE 子句。

其他 (others)

查詢樹的其他部分,像ORDER BY 子句,我們不準備在這裡討論。 規則系統在附加規則時將在那裡(ORDER BY 子句)替換一些條目, 但是這對於規則系統的基本原理並沒有多大關係。