CREATE RULE 中文man頁面
NAME
CREATE RULE - 定義一個新的重寫規則
SYNOPSIS
CREATE [ OR REPLACE ] RULE name AS ON event TO table [ WHERE condition ] DO [ INSTEAD ] { NOTHING | command | ( command ; command ... ) }
DESCRIPTION 描述
CREATE RULE 定義一個適用于特定表或者視圖的新規則。 CREATE OR REPLACE RULE 要么是創建一個新規則, 要么是用一個同表上的同名規則替換現有規則。
PostgreSQL規則系統允許我們在從數據庫或表中更新, 插入或刪除東西時定義一個其它的動作來執行。 簡單說,規則就是當我們在指定的表上執行指定的動作的時候,導致一些額外的動作被執行。 另外,規則可以用另外一個命令取代某個特定的命令,或者令命令完全不被執行。 規則還用于實現表視圖。我們要明白的是規則實際上只是一個命令轉換機制,或者說命令宏。 這種轉換發生在命令開始執行之前。如果你實際上想要一個為每個物理行獨立發生的操作, 那么你可能還是要用一個觸發器,而不是規則。有關規則的更多信息可以在 ``The Rule System'' 找到。
目前,ON SELECT 規則必須是無條件的 INSTEAD 規則并且必須有一個由一條 SELECT 查詢組成的動作。 因此,一條 ON SELECT 規則有效地把對象表轉成視圖, 它的可見內容是規則的 SELECT 查詢返回的記錄而不是存儲在表中的內容(如果有的話)。 我們認為寫一條 CREATE VIEW 命令比創建一個表然后定義一條 ON SELECT 規則在上面的風格要好。
你可以創建一個可以更新的視圖的幻覺, 方法是在視圖上定義 ON INSERT,ON UPDATE,和 ON DELETE 規則(或者滿足你需要的任何上述規則的子集),用合適的對其它表的更新替換在視圖上更新的動作。
如果你想在視圖更新上使用條件規則,那么這里就有一個補充: 對你希望在視圖上允許的每個動作,你都必須有一個無條件的 INSTEAD 規則。 如果規則是有條件的,或者它不是 INSTEAD, 那么系統仍將拒絕執行更新動作的企圖,因為它認為它最終會在某種程度上在虛擬表上執行動作。 如果你想處理條件規則上的所由有用的情況,那也可以;只需要增加一個無條件的 DO INSTEAD NOTHING 規則確保系統明白它將決不會被調用來更新虛擬表就可以了。 然后把條件規則做成非 INSTEAD;在這種情況下,如果它們被觸發,那么它們就增加到缺省的 INSTEAD NOTHING 動作中。
PARAMETERS 參數
- name
創建的規則名。它必須在同一個表上的所有規則的名字中唯一。 同一個表上的同一個事件類型的規則是按照字母順序運行的。- event
事件是 SELECT, UPDATE,DELETE 或 INSERT 之一。- table
規則施用的表或者視圖的名字(可以有模式修飾)。- condition
任意 SQL 條件表達式(返回 boolean)。 條件表達式除了引用 NEW 和 OLD 之外不能引用任何表,并且不能有聚集函數。- command
組成規則動作的命令。有效的命令是 SELECT,INSERT, UPDATE,DELETE,或 NOTIFY 語句之一。
在 condition 和 command 里, 特殊表名字 NEW 和 OLD 可以用于指向被引用表里的數值 new 在 ON INSERT 和 ON UPDATE 規則里可以指向被插入或更新的新行。 OLD 在 ON UPDATE,和 ON DELETE 規則里可以指向現存的被更新,或者刪除的行。
NOTES 注意
為了在表上定義規則,你必須有 RULE 權限。
有一件很重要的事情是要避免循環規則。 比如,盡管下面兩條規則定義都是 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 NOTIFY mytable; UPDATE mytable SET name = 'foo' WHERE id = 42;
里,一個 NOTIFY 事件將在 UPDATE 的時候發出,不管是否有某行的 id = 42。這是一個實現的限制,將來的版本應該修補這個毛病。
#p#
NAME
CREATE RULE - define a new rewrite rule
SYNOPSIS
CREATE [ OR REPLACE ] RULE name AS ON event TO table [ WHERE condition ] DO [ INSTEAD ] { NOTHING | command | ( command ; command ... ) }
DESCRIPTION
CREATE RULE defines a new rule applying to a specified table or view. CREATE OR REPLACE RULE will either create a new rule, or replace an existing rule of the same name for the same table.
The PostgreSQL rule system allows one to define an alternate action to be performed on insertions, updates, or deletions in database tables. Roughly speaking, a rule causes additional commands to be executed when a given command on a given table is executed. Alternatively, a rule can replace a given command by another, or cause a command not to be executed at all. Rules are used to implement table views as well. It is important to realize that a rule is really a command transformation mechanism, or command macro. The transformation happens before the execution of the commands starts. If you actually want an operation that fires independently for each physical row, you probably want to use a trigger, not a rule. More information about the rules system is in the chapter called ``The Rule System'' in the documentation.
Presently, ON SELECT rules must be unconditional INSTEAD rules and must have actions that consist of a single SELECT command. Thus, an ON SELECT rule effectively turns the table into a view, whose visible contents are the rows returned by the rule's SELECT command rather than whatever had been stored in the table (if anything). It is considered better style to write a CREATE VIEW command than to create a real table and define an ON SELECT rule for it.
You can create the illusion of an updatable view by defining ON INSERT, ON UPDATE, and ON DELETE rules (or any subset of those that's sufficient for your purposes) to replace update actions on the view with appropriate updates on other tables.
There is a catch if you try to use conditional rules for view updates: there must be an unconditional INSTEAD rule for each action you wish to allow on the view. If the rule is conditional, or is not INSTEAD, then the system will still reject attempts to perform the update action, because it thinks it might end up trying to perform the action on the dummy table of the view in some cases. If you want to handle all the useful cases in conditional rules, you can; just add an unconditional DO INSTEAD NOTHING rule to ensure that the system understands it will never be called on to update the dummy table. Then make the conditional rules not INSTEAD; in the cases where they are applied, they add to the default INSTEAD NOTHING action.
PARAMETERS
- name
- The name of a rule to create. This must be distinct from the name of any other rule for the same table. Multiple rules on the same table and same event type are applied in alphabetical name order.
- event
- The even is one of SELECT, INSERT, UPDATE, or DELETE.
- table
- The name (optionally schema-qualified) of the table or view the rule applies to.
- condition
- Any SQL conditional expression (returning boolean). The condition expression may not refer to any tables except NEW and OLD, and may not contain aggregate functions.
- command
- The command or commands that make up the rule action. Valid commands are SELECT, INSERT, UPDATE, DELETE, or NOTIFY.
Within condition and command, the special table names NEW and OLD may be used to refer to values in the referenced table. NEW is valid in ON INSERT and ON UPDATE rules to refer to the new row being inserted or updated. OLD is valid in ON UPDATE and ON DELETE rules to refer to the existing row being updated or deleted.
NOTES
You must have the privilege RULE on a table to be allowed to define a rule on it.
It is very important to take care to avoid circular rules. For example, though each of the following two rule definitions are accepted by PostgreSQL, the SELECT command would cause PostgreSQL to report an error because the query cycled too many times:
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;
Presently, if a rule action contains a NOTIFY command, the NOTIFY command will be executed unconditionally, that is, the NOTIFY will be issued even if there are not any rows that the rule should apply to. For example, in
CREATE RULE notify_me AS ON UPDATE TO mytable DO NOTIFY mytable; UPDATE mytable SET name = 'foo' WHERE id = 42;
one NOTIFY event will be sent during the UPDATE, whether or not there are any rows with id = 42. This is an implementation restriction that may be fixed in future releases.