PostgreSQL:RULE

Ryan_Bai發表於2020-12-18

語法

postgres=# \h create rule
Command: CREATE RULE
Description: define a new rewrite rule
Syntax:
CREATE [ OR REPLACE ] RULE name AS ON event
TO table_name [ WHERE condition ]
DO [ ALSO | INSTEAD ] { NOTHING | command | ( command ; command ... ) }
  • event: 觸發事件

    • SELECT:當 SQL 的查詢計劃中存在查詢表的操作時會重寫查詢計劃。

    • INSERT:當 SQL 的查詢計劃中存在向表中插入資料的操作時會重寫查詢計劃。

    • UPDATE:當 SQL 的查詢計劃中存在向表中更新資料的操作時會重寫查詢計劃

    • DELETE:當 SQL 的查詢計劃中存在向表中資料刪除的操作時會重寫查詢計劃

  • ALSO:被觸發的表插入一條資料的資料,觸發在另一個表裡面也插入一條(日誌記錄)。

  • INSTEAD:向被觸發的表插入一條資料的時候,用插入到其他表來代替(分割槽表)。

  • NOTHING:表示什麼都不執行

許可權

規則是從屬於表或試圖的。如果一張表屬於一個使用者,則這張表上的所有規則都屬於這個使用者。

對比

  • 規則系統是透過查詢重寫來實現的,修改查詢或生成額外的查詢不容易理解

  • 觸發器是為每一行都觸發執行一次,但從概念上比規則的方法簡單,更容易讓新手掌握

例項

準備

建表(訂單表+訂單日誌表)

postgres=# create table orders(id serial,name character varying,goods_id integer);
 CREATE TABLE
 postgres=# \d orders
Table "public.orders"
 Column    |               Type|Modifiers  
 ----------+-------------------+-----------------------------------------------------
        id |           integer | not null default nextval('orders_id_seq'::regclass)
      name | character varying | 
  goods_id | integer 
 postgres=# create table orders_log(id serial,do_type character varying,old_value character varying,new_value character varying,do_time timestamp without time zone not null default now());
 CREATE TABLE
 postgres=# \d orders_log
Table "public.orders_log"
 Column     |Type                         |Modifiers  
 -----------+-----------------------------+---------------------------------------------------------
          id|                     integer | not null default nextval('orders_log_id_seq'::regclass)
    do_type |           character varying | 
  old_value |           character varying | 
  new_value |           character varying | 
    do_time | timestamp without time zone | not null default now()

實驗

create rule on orders table(rule的作用是將對orders表的操作以日誌的方式插入到 orders_log 表中)

  • 記錄 insert 操作的 rule

    create or replace rule rule_orders_insert_log as on insert to orders 
    do also insert into orders_log(do_type,new_value) 
    values('insert',new.id||','||new.name||','||new.goods_id);
  • 記錄 update 操作的 rule

    create or replace rule rule_orders_update_log as on update to orders 
    do also insert into orders_log(do_type,old_value,new_value) 
    values('update',old.id||','||old.name||','||old.goods_id,new.id||','||new.name||','||new.goods_id);
  • 記錄 delete 操作的 rule

    create or replace rule rule_orders_delete_log as on delete to orders 
    do also insert into orders_log(do_type,old_value) 
    values('delete',old.id||','||old.name||','||old.goods_id);
  • rule 不像 function,觸發器一樣獨立存在的,而是依附於表上,當你把表刪了,相應的rule就一起被刪了。

    postgres=# \d orders
     Table "public.orders"
        Column|               Type|Modifiers  
    ----------+-------------------+-----------------------------------------------------
           id |           integer | not null default nextval('orders_id_seq'::regclass)
         name | character varying | 
     goods_id |           integer | 
    Rules:
    rule_orders_delete_log AS
    ON DELETE TO orders DOINSERT INTO orders_log (do_type, old_value)
    VALUES ('delete'::character varying, ((((old.id || ','::text) || old.name::text) || ','::text) || old.goods_id))
    rule_orders_insert_log AS
    ON INSERT TO orders DOINSERT INTO orders_log (do_type, new_value)
    VALUES ('insert'::character varying, ((((new.id || ','::text) || new.name::text) || ','::text) || new.goods_id))
    rule_orders_update_log AS
    ON UPDATE TO orders DOINSERT INTO orders_log (do_type, old_value, new_value)
    VALUES ('update'::character varying, ((((old.id || ','::text) || old.name::text) || ','::text) || old.goods_id), ((((new.id || ','::text) || new.name::text) || ','::text) || new.goods_id))
  • 使用驗證

    • 插入驗證

      postgres=# insert into orders(name,goods_id) values('aa',101);
      INSERT 0 1
      postgres=# insert into orders(name,goods_id) values('bb',102);
      INSERT 0 1

      檢視 orders 表和 orders_log 中的資料

      postgres=# select * from orders;
       id | name | goods_id 
      ----+------+----------
        1 |   aa |101
        3 |   bb |102
      (2 rows)
        
      postgres=# select * from orders_log;
       id | do_type | old_value | new_value |do_time 
      ----+---------+-----------+-----------+----------------------------
        1 |   insert|           |   2,aa,101| 2015-04-06 17:15:20.088412
        2 |   insert|           |   4,bb,102| 2015-04-06 17:15:28.150866
      (2 rows)
    • 修改驗證

      update orders set name ='cc',goods_id=201 where id=1;

      檢視orders表和orders_log中的資料:

      postgres=# select * from orders;
      id | name | goods_id 
      ---+------+----------
       3 | bb   |102
       1 | cc   |201
       (2 rows)
        
      postgres=# select * from orders_log;
       id | do_type | old_value | new_value |do_time 
      ----+---------+-----------+-----------+----------------------------
        1 |   insert|           |   2,aa,101| 2015-04-06 17:15:20.088412
        2 |   insert|           |   4,bb,102| 2015-04-06 17:15:28.150866
        3 |   update|   1,aa,101|   1,cc,201| 2015-04-06 17:18:07.127828
      (3 rows)
    • 刪除驗證

      delete from orders where id=1;

      檢視orders表和orders_log中的資料

      postgres=# select * from orders;
       id | name | goods_id 
      ----+------+----------
        3 | bb   |102
      (1 row)
        
      postgres=# select * from orders_log;
       id | do_type | old_value | new_value |do_time
      ----+---------+-----------+-----------+----------------------------
        1 |   insert|           |   2,aa,101| 2015-04-06 17:15:20.088412
        2 |   insert|           |   4,bb,102| 2015-04-06 17:15:28.150866
        3 |   update|   1,aa,101|   1,cc,201| 2015-04-06 17:18:07.127828
        4 |   delete|   1,cc,201|           | 2015-04-06 17:19:20.672241
      (4 rows)


大部分內容轉自:https://blog.csdn.net/luojinbai/article/details/44903589

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/31490526/viewspace-2743531/,如需轉載,請註明出處,否則將追究法律責任。

相關文章