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