CREATE RULE — 定義新的重寫規則
CREATE [ OR REPLACE ] RULEname
AS ONevent
TOtable_name
[ WHEREcondition
] DO [ ALSO | INSTEAD ] { NOTHING |command
| (command
;command
... ) } whereevent
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 INSERT
、ON UPDATE
和 ON DELETE
規則(或任何足以滿足您目的的子集)來建立可更新檢視表的假象,以將檢視表上的更新操作替換為其他資料表上的適當更新。 如果您想要支援 INSERT RETURNING
等等,請務必在這些規則的每一個中放置合適的 RETURNING
子句。
如果您嘗試將條件規則用於複雜的檢視表更新,則存在一個問題:對於您希望允許在檢視表上執行的每個操作,必須有一個無條件的 INSTEAD
規則。 如果規則是有條件的,或者不是 INSTEAD
,則系統仍然會拒絕執行更新操作的嘗試,因為它認為在某些情況下,它可能最終嘗試對檢視表的虛擬資料表執行該操作。 如果您想要在條件規則中處理所有有用的情況,請添加一個無條件的 DO INSTEAD NOTHING
規則,以確保系統了解它永遠不會被要求更新虛擬資料表。 然後使條件規則成為非 INSTEAD
;在應用它們的情況下,它們會添加到預設的 INSTEAD NOTHING
操作中。 (但是,此方法目前不適用於支援 RETURNING
查詢。)
一個足夠簡單可以自動更新的檢視表(參見 CREATE VIEW)不需要使用者建立的規則即可進行更新。 雖然您可以建立一個顯式的規則,但自動更新轉換通常會優於顯式規則。
另一個值得考慮的替代方法是使用 INSTEAD OF
觸發器(參見 CREATE TRIGGER)來代替規則。
name
要建立的規則的名稱。 這必須與同一資料表的任何其他規則的名稱不同。 同一資料表和相同事件類型的多個規則按字母順序應用。
event
事件是 SELECT
、INSERT
、UPDATE
或 DELETE
之一。 請注意,包含 ON CONFLICT
子句的 INSERT
不能用於具有 INSERT
或 UPDATE
規則的資料表。 請考慮改用可更新的檢視表。
table_name
規則適用的資料表或檢視表的名稱(可選擇包含模式限定詞)。
condition
任何SQL條件表達式(傳回 boolean
)。 條件表達式不能引用任何資料表,除了 NEW
和 OLD
,並且不能包含彙總函式。
INSTEAD
INSTEAD
表示指令應該 取代 原始指令來執行。
ALSO
ALSO
表示指令應該 除了 原始指令之外執行。
如果未指定 ALSO
和 INSTEAD
,則預設為 ALSO
。
command
構成規則動作的指令。 有效的指令是 SELECT
、INSERT
、UPDATE
、DELETE
或 NOTIFY
。
在 condition
和 command
之中,可以使用特殊的表名稱 NEW
和 OLD
來參照被參考表格中的值。NEW
在 ON INSERT
和 ON UPDATE
規則中有效,用來參照正在插入或更新的新列。OLD
在 ON UPDATE
和 ON DELETE
規則中有效,用來參照正在更新或刪除的現有列。
您必須是表格的擁有者,才能建立或變更表格的規則。
在視窗 (view) 的 INSERT
、UPDATE
或 DELETE
規則中,您可以新增一個 RETURNING
子句,該子句會發出視窗的欄位。如果該規則是由 INSERT RETURNING
、UPDATE RETURNING
或 DELETE 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 語言擴充功能,整個查詢重寫系統也是如此。
如果您在文件中發現任何不正確、與您使用特定功能的經驗不符或需要進一步澄清之處,請使用此表單回報文件問題。