| PostgreSQL 7.4 文檔 | ||||
|---|---|---|---|---|
| Prev | Fast Backward | Fast Forward | Next | |
本章討論 PostgreSQL 裡的規則系統。 生產規則系統的概念是很簡單的,但是在實際使用的時候會碰到很多細微的問題。
有些其它的數據庫系統定義動態的數據庫規則。這些通常是存儲過程和觸發器, 在 PostgreSQL 裡,這些東西也可以通過函數和觸發器來實現。
規則系統,(更準確地說,查詢重寫規則系統)是和存儲過程和觸發器完全不同的東西。 它把查詢修改為需要考慮規則的形式,然後把修改過的查詢傳遞給查詢規劃器執行。 這是非常有效的工具並且可以用于許多象查詢語言過程,視圖,和版本等。 這個規則系統的理論基礎和能力在 有關數據庫系統的規則,過程,緩存和視圖 和 A Unified Framework for Version Modeling Using Production Rules in a Database System 裡有討論。
要理解規則系統如何工作,首先要知道規則何時被激發以及它的輸入和結果是什麼。
規則系統位于分析器和規劃器之間。以分析器的輸出 -- 一個查詢樹, 以及用戶定義的重寫規則作為輸入, 重寫規則也是一個查詢樹,只不過增加了一些擴展信息, 然後創建零個或者多個查詢樹作為結果。 所以它的輸入和輸出仍然是那些分析器可以生成的東西, 因而任何它(規則系統)看到的東西都是可以用 SQL 語句表達的。
那麼什麼是查詢樹呢? 它是一個 SQL 語句的內部表現形式, 這時組成該語句的每個獨立地部分都是分別存儲的。 如果你設置了配置參數 debug_print_parse, debug_print_rewritten,或 debug_print_plan, 那麼你可以在服務器日志中看到這些查詢樹。 規則動作也是以查詢樹的方式存儲的,存放在系統表pg_rewirte 裡面。不過不是用象調試輸出那樣的格式,但包含的內容是完全一樣的。
閱讀一個裸查詢樹需要一定的經驗, 但是因為理解查詢樹的 SQL 表現就足以理解規則系統, 所以這份文檔將不會告訴你如何讀取它們。
當我們讀取本章中查詢樹的 SQL 表現時, 我們必須能夠識別該語句被分解後放在查詢樹裡的成員。 查詢樹的成員有
這是一個簡單的值,說明哪條命令 (SELECT,INSERT,UPDATE,DELETE) 生成這個查詢樹。
範圍表是一個查詢中使用的關系的列表。 在SELECT語句裡是在FORM關鍵字後面給出的關系。
每個範圍表表示一個表或一個視圖,表明是查詢裡哪個成員調用了它。 在查詢樹裡,範圍表是用代號而不是用名字引用的, 所以這裡不用象在 SQL語句裡一樣關心是否有重名問題。 這種情況在引入了規則的範圍表後可能會發生。 本章的例子將不討論這種情況。
這是一個範圍表的索引,用于標識查詢結果前往的表。
SELECT查詢通常沒有結果關系表。特例SELECT INTO 幾乎等于一個 CREATE TABLE, INSERT ... SELECT序列,所以這裡我們就不單獨討論了。
在INSERT,UPDATE和DELETE命令裡, 結果關系是更改發生影響的表(或視圖!)。
目標列是一列定義查詢結果的表達式。在SELECT的情況下, 這些表達式就是構建查詢的最終輸出的東西。 它們是位于SELECT和FROM關鍵字之間的表達式 (* 只是表明一個關系的所有字段的縮寫,它被分析器擴展為獨立的字段, 因此規則系統永遠看不到它)。
DELETE 不需要目標列是因為它們不產生任何結果。 實際上規劃器會向空目的標列中增加一條特殊的CTID記錄。 但這是在規則系統之後並且我們將稍後討論;對于規則系統而言,目標列是空的。
對于INSERT命令裡面,目標列描述了應該進入結果關系的新行。 這些由那些在VALUES子句裡的表達式或在 INSERT ... SELECT 語句裡的 SELECT 子句裡面的表達式構成。 重寫過程的第一步就是為任何不是由原始的查詢賦值,並且有缺省值的字段增加目標列表項。 任何其它的字段(既無給出值,也無缺省的)將由規劃器自動賦予一個常量 NULL 表達式。
對于UPDATE命令,它(目標列)描述應該替換舊行的新行。 在規則系統裡,它只包含來自查詢的 SET attribute = expression部分抽取的表達式。 這時,規劃器將通過插入從舊行抽取數據到新行的表達式的方法處理缺失的字段。 並且它也會象 在DELETE裡那樣增加特殊的CTID記錄。
目標列裡的每個元素都包含著一個表達式, 它可以為常量值,可以為一個指向某個範圍表裡面的關系的一個字段的變量, 可以為一個由函數調用,常量,變量,操作符等構成的表達式樹。
查詢條件是一個表達式,它非常類似那些包含在目標列裡的條目。 這個表達式的值是一個布爾值,通過此值來判斷對最終結果行是否要執操作 (INSERT,UPDATE,DELETE 或 SELECT)。 它是一個SQL 語句 的WHERE子句。
查詢的連接樹顯示了FROM 子句的結構。 對于象SELECT FROM a, b, c這樣的簡單查詢, 連接樹只是一個FROM項的簡單列表, 因為我們允許以任意順序連接它們。 但如果使用了 JOIN 表達式 --- 尤其是 outer join 的時候, 我們就必須按照該連接顯示的順序進行連接。 連接樹顯示 JOIN 表達式的結構。 與特定的 JOIN 子句(來自 ON 或者 USING 表達式)相關的限制做為附加在那些連接樹節點的條件表達式存儲。 事實證明把頂層 WHERE 表達式也當做附加在頂層連接樹項的條件來存儲是非常方便的。所以實際上連接樹代表SELECT語句的 FROM 和 WHERE 子句。
查詢樹的其他部分,像ORDER BY 子句,我們不準備在這裡討論。 規則系統在附加規則時將在那裡(ORDER BY 子句)替換一些條目, 但是這對于規則系統的基本原理並沒有多大關系。