?
Ce document utilise Manuel du site Web PHP chinois Libérer
CREATE [ OR REPLACE ] RULE name AS ON event TO table [ WHERE condition ] DO [ ALSO | INSTEAD ] { NOTHING | command | ( command ; command ... ) }
CREATE RULE定義一個適用于特定表或者視圖的新規(guī)則。 CREATE OR REPLACE RULE要么是創(chuàng)建一個新規(guī)則, 要么是替換一個表上的同名規(guī)則。
PostgreSQL規(guī)則系統(tǒng)允許在更新、插入、刪除 時執(zhí)行一個其它的預定義動作。簡單的說,規(guī)則就是在指定表上執(zhí)行指定動作 的時候,將導致一些額外的動作被執(zhí)行。另外,一個INSTEAD 規(guī)則可以用另外一個命令取代特定的命令,或者令完全不執(zhí)行該命令。規(guī)則 還可以用于實現表視圖。規(guī)則實際上只是一個命令轉換機制,或者說命令宏。 這種轉換發(fā)生在命令開始執(zhí)行之前。如果你想要針對每個物理行獨立發(fā)生的操作, 那么可能應該使用觸發(fā)器而不是規(guī)則。有關規(guī)則的更多信息可以在 Chapter 37找到。
目前,ON SELECT規(guī)則必須是無條件的 INSTEAD規(guī)則并且必須有一個由單獨一條 SELECT查詢組成的動作。因此,一條 ON SELECT規(guī)則有效地把表轉成視圖,它的 可見內容是規(guī)則的SELECT查詢返回的記錄而 不是存儲在表中的內容。寫一條CREATE VIEW 命令比創(chuàng)建一個表然后在上面定義一條ON SELECT 規(guī)則的風格要好。
你可以創(chuàng)建一個允許更新的視圖的幻覺,方法是在視圖上定義ON INSERT,ON UPDATE,ON DELETE規(guī)則 (或者滿足你需要的任何上述規(guī)則的子集),用合適的對其它表的更新替換在視圖上更新的動作。 如果打算支持INSERT RETURNING之類,就必須確保在規(guī)則的結尾放置恰當的RETURNING子句。
如果你想在視圖更新上使用條件規(guī)則,那么這里就有一個補充:對你希望在視圖上允許的每個動作, 你都必須有一個無條件的INSTEAD規(guī)則。如果規(guī)則是有條件的或者它不是INSTEAD, 那么系統(tǒng)仍將拒絕執(zhí)行更新動作,因為它認為最終會在視圖的虛擬表上執(zhí)行這個動作。如果你想處理條件規(guī)則上的所有有用的情況, 那只需要增加一個無條件的DO INSTEAD NOTHING規(guī)則確保系統(tǒng)明白它決不會被調用來更新虛擬表就可以了。 然后把條件規(guī)則做成非INSTEAD;在這種情況下,如果它們被觸發(fā),那么它們就增加到缺省的INSTEAD NOTHING動作中。不過這種方法目前不支持RETURNING查詢。
創(chuàng)建的規(guī)則名。它必須在同一個表上的所有規(guī)則名字中唯一。同一個表上的同一個事件類型的規(guī)則是按照字母順序運行的。
INSERT,UPDATE, DELETE事件之一。
規(guī)則作用的表或者視圖的名字(可以有模式修飾)。
任意返回boolean的SQL條件表達式。條件表達式除了引用NEW和OLD之外不能引用任何表,并且不能有聚集函數。
指示使用該命令代替最初的命令。
ALSO指示命令應該被執(zhí)行,除了 初始命令。 該命令應該在最初的命令執(zhí)行之后一起執(zhí)行。
若ALSO和INSTEAD均未指定, 那么就默認為ALSO。 如果既沒有聲明ALSO也沒有聲明 INSTEAD,那么ALSO是缺省。
命令或者彌補規(guī)則操作的命令。有效命令是SELECT, INSERT, UPDATE, DELETE,或者NOTIFY. 組成規(guī)則動作的命令。有效的命令是SELECT, INSERT,UPDATE, DELETE,NOTIFY語句之一。
在condition和command里,特殊的表名字NEW和OLD可以用于指向被引用表里的數值。 NEW在ON UPDATE和ON UPDATE規(guī)則里可以指向被插入或更新的新行。OLD在ON UPDATE和ON DELETE規(guī)則里可以指向現存的被更新或刪除的行。 在condition和 command中,特殊表名 NEW和OLD可以用來指代所引用的 表中的值。NEW對 ON INSERT和ON UPDATE規(guī)則 引用插入或更新新行是有效的, OLD對ON UPDATE 和ON DELETE規(guī)則引用更新或刪除現有行是有效的。
為了在表上定義或修改規(guī)則,你必須是該表的擁有者。
在視圖上用于INSERT,UPDATE,DELETE的規(guī)則中可以添加RETURNING子句基于視圖的字段返回。 如果規(guī)則被INSERT RETURNING,UPDATE RETURNING,DELETE RETURNING命令觸發(fā),這些子句將用來計算輸出結果。 如果規(guī)則被不帶RETURNING的命令觸發(fā),那么規(guī)則的RETURNING子句將被忽略。目前僅允許無條件的 INSTEAD 規(guī)則包含 RETURNING 子句, 而且在同一個事件內的所有規(guī)則中最多只能有一個 RETURNING 子句。這樣就確保只有一個RETURNING子句可以用于計算結果。 如果在任何有效規(guī)則中都不存在RETURNING子句,該視圖上的RETURNING查詢將被拒絕。
有一件很重要的事情是要避免循環(huán)規(guī)則。比如,盡管下面兩條規(guī)則定義都是PostgreSQL可以接受的, 但其中的一條SELECT命令會導致PostgreSQL報告一條錯誤信息,因為該查詢循環(huán)了太多次:
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;
目前,如果一個規(guī)則包含一個NOTIFY命令,那么該NOTIFY命令將被無條件執(zhí)行, 也就是說,即使規(guī)則不施加到任何行上面,該NOTIFY也會被執(zhí)行。比如,在:
CREATE RULE notify_me AS ON UPDATE TO mytable DO ALSO NOTIFY mytable; UPDATE mytable SET name = 'foo' WHERE id = 42;
里,一個NOTIFY事件將在UPDATE的時候發(fā)出, 不管是否有滿足id = 42條件的行。 這是一個實現的限制,將來的版本應該修補這個毛病。
CREATE RULE是PostgreSQL語言的擴展, 整個規(guī)則重寫系統(tǒng)都是如此。