CREATE RULE用於定義一條應用於指定表或視圖的新規則。
簡介
CREATE RULE定義一條應用於指定表或視圖的新規則。CREATE OR REPLACE RULE將建立一條新規則或者替換同一個表上具有同一名稱的現有規則。
PolarDB規則系統允許我們定義針對資料庫表中插入、更新或者刪除動作上的替代動作。大約來說,當在一個給定表上執行給定命令時,一條規則會導致執行額外的命令。或者, INSTEAD規則可以用另一個命令替換給定的命令,或者導致一個命令根本不被執行。規則也被用來實現 SQL 檢視。規則實際上是一種命令轉換機制或者命令宏。這種轉換會在命令的執行開始之前進行。 如果你實際上想要為每一個物理行獨立地觸發一個操作,你可能更需要一個觸發器而不是規則。
當前,ON SELECT規則必須是無條件 INSTEAD規則並且其動作必須由一個單一 SELECT命令構成。因此,一條 ON SELECT規則實際上把表變成了一個視圖,它的可見內容是由該規則的SELECT命令返回,而不是直接存在該表中的內容(如果有)。不過,使用 CREATE VIEW命令還是要比建立一個真實表並且在其上定義一條ON SELECT規則更好。
可以通過定義ON INSERT、ON UPDATE 以及ON DELETE規則(或者這些規則的任意子集)來建立可更新的視圖,這些規則可以把視圖上的更新動作替換為其他表上適當的更新動作。如果想要支援INSERT RETURNING等等,那麼一定要在每一個這類規則中放上一個合適的RETURNING子句。
如果你嘗試為複雜視圖更新使用有條件的規則,有一點是很重要的:對於在該視圖上允許的每一個動作,必須有一條 INSTEAD規則。如果該規則是有條件的,或者不是 INSTEAD,那麼系統仍將拒絕嘗試執行該更新動作, 因為它會認為在某些情況下它應該停止嘗試在該視圖的傀儡表上執行動作。 如果你想處理有條件規則中的所有有用的情況,可以增加一條無條件的 DO INSTEAD NOTHING規則來確保系統理解它將永遠不會被調用來更新傀儡表。然後讓有條件規則變成非-INSTEAD。在它們適用的情況下,它們會加到預設的INSTEAD NOTHING動作(不過,當前這種方法不支援RETURNING查詢)。
文法
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 VIEW),它們不需要依靠使用者建立的規則來變成可更新的。不過還是可以建立一條顯式規則,自動更新轉換通常比顯式規則效率高。
另一種值得考慮的辦法是使用INSTEAD OF觸發器(見 CREATE TRIGGER)代替規則。
參數
name要建立的規則的名稱。它必須與同一個表上任何其他規則的名稱相區分。 同一個表上同一種事件類型的多條規則會按照其名稱的字元順序被應用。event時間是SELECT、INSERT、UPDATE或者DELETE之一。 注意包含ON CONFLICT子句的INSERT不能被用在具有INSERT或者UPDATE規則的表上。那種情況下請考慮使用可更新的視圖。table_name規則適用的表或者視圖的名稱(可以是模式限定的)。condition任意的 SQL 條件運算式(返回boolean)。該條件運算式不能引用除NEW以及OLD之外的任何錶,並且不能包含聚集合函式。INSTEADINSTEAD指示該命令應該取代 原始命令被執行。ALSOALSO指示應該在原始命令 之外執行這些命令。如果
ALSO和INSTEAD都沒有被指定, 預設是ALSO。command組成規則動作的命令。可用的命令有SELECT、INSERT、UPDATE、DELETE或者NOTIFY。在
condition和command中,名為NEW和OLD的表可以被用來引用被參考資料表中的值。在ON INSERT和ON UPDATE規則中,NEW被用來引用被插入或者更新的新行。在ON UPDATE和ON DELETE規則中,OLD被用來引用被更新或者刪除的現有行。
說明
要在表上建立或者修改規則,必須是表的擁有者。
在一條用於視圖上INSERT、UPDATE 或者DELETE的規則中, 可以增加一個RETURNING 子句來發出視圖的列。如果該規則被一個INSERT RETURNING、 UPDATE RETURNING或者 DELETE RETURNING命令觸發,這個子句將被用來計算輸出。 當規則被一個沒有RETURNING的命令觸發時,該規則的 RETURNING子句將被忽略。當前的實現只允許無條件 INSTEAD規則包含RETURNING。此外,用於同一事件的所有規則中至多隻能有一個RETURNING子句(這確保了只有一個候選RETURNING子句被用來計算結果)。如果在任何可用規則中都沒有RETURNING子句,視圖上的RETURNING查詢將被拒絕。
避免迴圈規則非常重要。例如,儘管下面的兩條規則定義都被 PolarDB所接受, SELECT命令將導致 PolarDB報告一個錯誤,因為會產生一條規則的遞迴擴充:
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。這是一種實現限制,它可能會在未來的發行中被修複。