W3Cschool
恭喜您成為首批注冊用戶
獲得88經(jīng)驗值獎勵
CREATE RULE — 定義一條新的重寫規(guī)則
CREATE [ OR REPLACE ] RULE name
AS ON event
TO table_name
[ WHERE condition
]
DO [ ALSO | INSTEAD ] { NOTHING | command
| ( command
; command
... ) }
其中 event
可以是以下之一:
SELECT | INSERT | UPDATE | DELETE
CREATE RULE
定義一條應(yīng)用于指定表或視圖的 新規(guī)則。CREATE OR REPLACE RULE
將創(chuàng)建一條 新規(guī)則或者替換同一個表上具有同一名稱的現(xiàn)有規(guī)則。
PostgreSQL規(guī)則系統(tǒng)允許我們定義 針對數(shù)據(jù)庫表中插入、更新或者刪除動作上的替代動作。大約來說,當(dāng)在 一個給定表上執(zhí)行給定命令時,一條規(guī)則會導(dǎo)致執(zhí)行額外的命令。或者, INSTEAD
規(guī)則可以用另一個命令替換給定的命令,或 者導(dǎo)致一個命令根本不被執(zhí)行。規(guī)則也被用來實現(xiàn) SQL 視圖。規(guī)則實際上 是一種命令轉(zhuǎn)換機制或者命令宏。這種轉(zhuǎn)換會在命令的執(zhí)行開始之前進行。 如果你實際上想要為每一個物理行獨立地觸發(fā)一個操作,你可能更需要一個
觸發(fā)器而不是規(guī)則。更多有關(guān)規(guī)則系統(tǒng)的信息請見第 40 章。
當(dāng)前,ON SELECT
規(guī)則必須是無條件 INSTEAD
規(guī)則并且其動作必須由一個單一 SELECT
命令構(gòu)成。因此,一條 ON SELECT
規(guī)則實際上把表變成了一個視圖,它的可見 內(nèi)容是由該規(guī)則的SELECT
命令返回,而不是直
接存在該表中的內(nèi)容(如果有)。不過,使用 CREATE VIEW
命令還是要比創(chuàng)建一個真實表并且 在其上定義一條ON SELECT
規(guī)則更好。
可以通過定義ON INSERT
、ON UPDATE
以及ON DELETE
規(guī)則(或者這些規(guī)則的任意子集)來創(chuàng)建 可更新的視圖,這些規(guī)則可以把視圖上的更新動作替換為其他表上適當(dāng)?shù)母?動作。如果想要支持INSERT RETURNING
等等,那么一定要 在每一個這類規(guī)則中放上一個合適的
RETURNING
子句。
如果你嘗試為復(fù)雜視圖更新使用有條件的規(guī)則,有一點是很重要的:對于 你希望在該視圖上允許的每一個動作,必須有一條 INSTEAD
規(guī)則。如果該規(guī)則是有條件的,或者不是 INSTEAD
,那么系統(tǒng)仍將拒絕嘗試執(zhí)行該更新動作, 因為它會認(rèn)為在某些情況下它應(yīng)該停止嘗試在該視圖的傀儡表上執(zhí)行動作。 如果你想處理有條件規(guī)則中的所有有用的情況,可以增加一條無條件的
DO INSTEAD NOTHING
規(guī)則來確保系統(tǒng)理解它將 永遠不會被調(diào)用來更新傀儡表。然后讓有條件規(guī)則變成 非-INSTEAD
。在它們適用的情況下,它們會加到 默認(rèn)的INSTEAD NOTHING
動作(不過,當(dāng)前這種方法不 支持RETURNING
查詢)。
足夠簡單的視圖自動就是可更新的(見CREATE VIEW),它們不需要依靠用戶創(chuàng)建的規(guī)則來變成可 更新的。不過還是可以創(chuàng)建一條顯式規(guī)則,自動更新轉(zhuǎn)換通常比顯式規(guī)則效 率高。
另一種值得考慮的辦法是使用INSTEAD OF
觸發(fā)器(見 CREATE TRIGGER)代替規(guī)則。
name
要創(chuàng)建的規(guī)則的名稱。它必須與同一個表上任何其他規(guī)則的名稱相區(qū)分。 同一個表上同一種事件類型的多條規(guī)則會按照其名稱的字符順序被應(yīng)用。
event
時間是SELECT
、 INSERT
、UPDATE
或者 DELETE
之一。 注意包含ON
CONFLICT
子句的INSERT
不能被用在具有INSERT
或者 UPDATE
規(guī)則的表上。那種情況下請考慮使用 可更新的視圖。
table_name
規(guī)則適用的表或者視圖的名稱(可以是模式限定的)。
condition
任意的SQL條件表達式(返回 boolean
)。該條件表達式不能引用除NEW
以及 OLD
之外的任何表,并且不能包含聚集函數(shù)。
INSTEAD
INSTEAD
指示該命令應(yīng)該取代
原始命令被執(zhí)行。
ALSO
ALSO
指示應(yīng)該在原始命令 之外執(zhí)行這些命令。
如果ALSO
和INSTEAD
都沒有被指定, 默認(rèn)是ALSO
。
command
組成規(guī)則動作的命令。可用的命令有SELECT
、 INSERT
、UPDATE
、 DELETE
或者NOTIFY
。
在condition
和 command
中,名為 NEW
和OLD
的表可以被用來引用被 引用表中的值。在ON INSERT
和 ON UPDATE
規(guī)則中,
NEW
被用來 引用被插入或者更新的新行。在ON UPDATE
和 ON DELETE
規(guī)則中,OLD
被用來引 用被更新或者刪除的現(xiàn)有行。
要在表上創(chuàng)建或者修改規(guī)則,必須是表的擁有者。
在一條用于視圖上INSERT
、UPDATE
或者DELETE
的規(guī)則中, 可以增加一個RETURNING
子句來發(fā)出視圖的列。如果該規(guī)則被一個INSERT RETURNING
、 UPDATE RETURNING
或者
DELETE RETURNING
命令觸發(fā),這個子句將被用來計算輸出。 當(dāng)規(guī)則被一個沒有RETURNING
的命令觸發(fā)時,該規(guī)則的 RETURNING
子句將被忽略。當(dāng)前的實現(xiàn)只允許無條件 INSTEAD
規(guī)則包含RETURNING
。此外,用于同一事件 的所有規(guī)則中至多只能有一個
RETURNING
子句(這確保了只有一個 候選RETURNING
子句被用來計算結(jié)果)。如果在任何可用規(guī)則中都 沒有RETURNING
子句,視圖上的RETURNING
查詢將 被拒絕。
避免循環(huán)規(guī)則非常重要。例如,盡管下面的兩條規(guī)則定義都被 PostgreSQL所接受, SELECT
命令將導(dǎo)致 PostgreSQL報告一個錯誤,因為會產(chǎn)生一條 規(guī)則的遞歸擴展:
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;
當(dāng)前,如果一個規(guī)則動作包含一個NOTIFY
命令, 該NOTIFY
命令將被無條件執(zhí)行,也就是說,即使 該規(guī)則不被應(yīng)用到任何行上,也會發(fā)出NOTIFY
。 例如,在
CREATE RULE notify_me AS ON UPDATE TO mytable DO ALSO NOTIFY mytable;
UPDATE mytable SET name = 'foo' WHERE id = 42;
中,UPDATE
期間將發(fā)出一個 NOTIFY
事件,不管是否有行匹配條件 id = 42
。這是一種實現(xiàn)限制,它可能會在未來的發(fā)行中被修復(fù)。
CREATE RULE
是一種 PostgreSQL語言擴展, 整個查詢重寫系統(tǒng)也是這樣。
Copyright©2021 w3cschool編程獅|閩ICP備15016281號-3|閩公網(wǎng)安備35020302033924號
違法和不良信息舉報電話:173-0602-2364|舉報郵箱:jubao@eeedong.com
掃描二維碼
下載編程獅App
編程獅公眾號
聯(lián)系方式:
更多建議: