支援的版本:目前 (17) / 16 / 15 / 14 / 13
開發版本:devel
不支援的版本:12 / 11 / 10 / 9.6 / 9.5 / 9.4 / 9.3 / 9.2 / 9.1 / 9.0 / 8.4 / 8.3 / 8.2 / 8.1 / 8.0 / 7.4 / 7.3 / 7.2 / 7.1

CREATE RULE

CREATE RULE — 定義新的重寫規則

概要

CREATE [ OR REPLACE ] RULE name AS ON event
    TO table_name [ WHERE condition ]
    DO [ ALSO | INSTEAD ] { NOTHING | command | ( command ; command ... ) }

where event can be one of:

    SELECT | INSERT | UPDATE | DELETE

描述

CREATE RULE 定義一個新的規則,適用於指定的資料表或檢視表。CREATE OR REPLACE RULE 將會建立一個新的規則,或者替換同一個資料表上相同名稱的現有規則。

PostgreSQL 規則系統允許定義一個替代動作,以在資料庫資料表中的插入、更新或刪除操作時執行。粗略地說,規則會在給定的資料表上執行給定的指令時,導致額外的指令被執行。 或者,INSTEAD 規則可以用另一個指令來取代給定的指令,或者使指令根本不被執行。 規則也用於實現 SQL 檢視表。 重要的是要意識到,規則實際上是一種指令轉換機制,或指令巨集。 轉換發生在指令開始執行之前。 如果您實際上想要一個為每個物理行獨立觸發的操作,您可能需要使用觸發器,而不是規則。 有關規則系統的更多信息,請參閱第 39 章

目前,ON SELECT 規則只能附加到檢視表。 這樣的規則必須命名為 "_RETURN",必須是一個無條件的 INSTEAD 規則,並且必須有一個動作,該動作包含單個 SELECT 指令。 此指令定義檢視表的可見內容。 (檢視表本身基本上是一個沒有儲存的虛擬資料表。) 最好將此類規則視為實作細節。 雖然可以透過 CREATE OR REPLACE RULE "_RETURN" AS ... 重新定義檢視表,但最好使用 CREATE OR REPLACE VIEW

您可以通過定義 ON INSERTON UPDATEON DELETE 規則(或任何足以滿足您目的的子集)來建立可更新檢視表的假象,以將檢視表上的更新操作替換為其他資料表上的適當更新。 如果您想要支援 INSERT RETURNING 等等,請務必在這些規則的每一個中放置合適的 RETURNING 子句。

如果您嘗試將條件規則用於複雜的檢視表更新,則存在一個問題:對於您希望允許在檢視表上執行的每個操作,必須有一個無條件的 INSTEAD 規則。 如果規則是有條件的,或者不是 INSTEAD,則系統仍然會拒絕執行更新操作的嘗試,因為它認為在某些情況下,它可能最終嘗試對檢視表的虛擬資料表執行該操作。 如果您想要在條件規則中處理所有有用的情況,請添加一個無條件的 DO INSTEAD NOTHING 規則,以確保系統了解它永遠不會被要求更新虛擬資料表。 然後使條件規則成為非 INSTEAD;在應用它們的情況下,它們會添加到預設的 INSTEAD NOTHING 操作中。 (但是,此方法目前不適用於支援 RETURNING 查詢。)

注意

一個足夠簡單可以自動更新的檢視表(參見 CREATE VIEW)不需要使用者建立的規則即可進行更新。 雖然您可以建立一個顯式的規則,但自動更新轉換通常會優於顯式規則。

另一個值得考慮的替代方法是使用 INSTEAD OF 觸發器(參見 CREATE TRIGGER)來代替規則。

參數

name

要建立的規則的名稱。 這必須與同一資料表的任何其他規則的名稱不同。 同一資料表和相同事件類型的多個規則按字母順序應用。

event

事件是 SELECTINSERTUPDATEDELETE 之一。 請注意,包含 ON CONFLICT 子句的 INSERT 不能用於具有 INSERTUPDATE 規則的資料表。 請考慮改用可更新的檢視表。

table_name

規則適用的資料表或檢視表的名稱(可選擇包含模式限定詞)。

condition

任何SQL條件表達式(傳回 boolean)。 條件表達式不能引用任何資料表,除了 NEWOLD,並且不能包含彙總函式。

INSTEAD

INSTEAD 表示指令應該 取代 原始指令來執行。

ALSO

ALSO 表示指令應該 除了 原始指令之外執行。

如果未指定 ALSOINSTEAD,則預設為 ALSO

command

構成規則動作的指令。 有效的指令是 SELECTINSERTUPDATEDELETENOTIFY

conditioncommand 之中,可以使用特殊的表名稱 NEWOLD 來參照被參考表格中的值。NEWON INSERTON UPDATE 規則中有效,用來參照正在插入或更新的新列。OLDON UPDATEON DELETE 規則中有效,用來參照正在更新或刪除的現有列。

注意

您必須是表格的擁有者,才能建立或變更表格的規則。

在視窗 (view) 的 INSERTUPDATEDELETE 規則中,您可以新增一個 RETURNING 子句,該子句會發出視窗的欄位。如果該規則是由 INSERT RETURNINGUPDATE RETURNINGDELETE RETURNING 指令觸發,則此子句將用於計算輸出。當規則由沒有 RETURNING 的指令觸發時,規則的 RETURNING 子句將被忽略。目前的實作僅允許無條件的 INSTEAD 規則包含 RETURNING;此外,在相同事件的所有規則中,最多只能有一個 RETURNING 子句。(這確保只有一個候選的 RETURNING 子句可被用來計算結果。)如果任何可用的規則中都沒有 RETURNING 子句,則會拒絕視窗上的 RETURNING 查詢。

非常重要的是,要注意避免循環規則。例如,雖然以下兩個規則定義都可以被 PostgreSQL 接受,但 SELECT 指令會導致 PostgreSQL 回報錯誤,因為規則的遞迴展開。

CREATE RULE "_RETURN" AS
    ON SELECT TO t1
    DO INSTEAD
        SELECT * FROM t2;

CREATE RULE "_RETURN" AS
    ON SELECT TO t2
    DO INSTEAD
        SELECT * FROM t1;

SELECT * FROM t1;

目前,如果規則動作包含 NOTIFY 指令,則 NOTIFY 指令將會無條件地執行,也就是說,即使沒有任何規則應該應用於的列,也會發出 NOTIFY。例如,在

CREATE RULE notify_me AS ON UPDATE TO mytable DO ALSO NOTIFY mytable;

UPDATE mytable SET name = 'foo' WHERE id = 42;

UPDATE 期間將會傳送一個 NOTIFY 事件,無論是否有任何列符合 id = 42 的條件。這是一個實作限制,可能會在未來的版本中修正。

相容性

CREATE RULE 是一個 PostgreSQL 語言擴充功能,整個查詢重寫系統也是如此。

提交更正

如果您在文件中發現任何不正確、與您使用特定功能的經驗不符或需要進一步澄清之處,請使用此表單回報文件問題。