天天看點

PostgreSQL Oracle 相容性之 - ALTER TRIGGER ENABLE|DISABLE

标簽

PostgreSQL , 觸發器 , enable , disable

https://github.com/digoal/blog/blob/master/201804/20180408_02.md#%E8%83%8C%E6%99%AF 背景

Oracle 臨時關閉或啟用觸發器的文法如下

https://docs.oracle.com/cd/B19306_01/server.102/b14200/statements_4001.htm
ALTER TRIGGER [ schema. ]trigger    
  { ENABLE    
  | DISABLE    
  | RENAME TO new_name    
  | COMPILE [ DEBUG ]    
      [ compiler_parameters_clause    
        [ compiler_parameters_clause ] ... ]    
      [ REUSE SETTINGS ]    
  } ;    
           

https://github.com/digoal/blog/blob/master/201804/20180408_02.md#postgresql-%E8%A7%A6%E5%8F%91%E5%99%A8%E5%BC%80%E5%85%B3%E8%AF%AD%E6%B3%95%E6%9B%B4%E4%B8%B0%E5%AF%8C%E4%B8%80%E4%BA%9B PostgreSQL 觸發器開關文法更豐富一些

PostgreSQL中對應的文法在alter table中,因為觸發器與表相關,這樣設計文法也符合邏輯的。

https://www.postgresql.org/docs/devel/static/sql-altertable.html
ALTER TABLE [ IF EXISTS ] [ ONLY ] name [ * ]    
    action [, ... ]    
    
    DISABLE TRIGGER [ trigger_name | ALL | USER ]    
    ENABLE TRIGGER [ trigger_name | ALL | USER ]    
    
    ENABLE REPLICA TRIGGER trigger_name    
    ENABLE ALWAYS TRIGGER trigger_name    
           

細節(注意觸發器被觸發還受制于session_replication_role參數與replica|always的配置。)

These forms configure the firing of trigger(s) belonging to the table. A disabled trigger is still known to the system, but is not executed when its triggering event occurs. For a deferred trigger, the enable status is checked when the event occurs, not when the trigger function is actually executed. One can disable or enable a single trigger specified by name, or all triggers on the table, or only user triggers (this option excludes internally generated constraint triggers such as those that are used to implement foreign key constraints or deferrable uniqueness and exclusion constraints). Disabling or enabling internally generated constraint triggers requires superuser privileges; it should be done with caution since of course the integrity of the constraint cannot be guaranteed if the triggers are not executed.

The trigger firing mechanism is also affected by the configuration variable session_replication_role. Simply enabled triggers (the default) will fire when the replication role is “origin” (the default) or “local”. Triggers configured as ENABLE REPLICA will only fire if the session is in “replica” mode, and triggers configured as ENABLE ALWAYS will fire regardless of the current replication role.

The effect of this mechanism is that in the default configuration, triggers do not fire on replicas. This is useful because if a trigger is used on the origin to propagate data between tables, then the replication system will also replicate the propagated data, and the trigger should not fire a second time on the replica, because that would lead to duplication. However, if a trigger is used for another purpose such as creating external alerts, then it might be appropriate to set it to ENABLE ALWAYS so that it is also fired on replicas.

This command acquires a SHARE ROW EXCLUSIVE lock.

trigger_name

Name of a single trigger to disable or enable.

ALL

Disable or enable all triggers belonging to the table. (This requires superuser privilege if any of the triggers are internally generated constraint triggers such as those that are used to implement foreign key constraints or deferrable uniqueness and exclusion constraints.)

USER

Disable or enable all triggers belonging to the table except for internally generated constraint triggers such as those that are used to implement foreign key constraints or deferrable uniqueness and exclusion constraints.

(内部用于foreign key, unique, 排他 等限制的觸發器除外)

關閉或開啟指定或所有表,或者某個使用者,某個schema下的所有表的觸發器。

使用函數,參考:

https://stackoverflow.com/questions/3942258/how-do-i-temporarily-disable-triggers-in-postgresql
For example if you have tables in a particular namespace it could be:

create or replace function disable_triggers(a boolean, nsp character varying) returns void as
$$
declare 
act character varying;
r record;
begin
    if(a is true) then
        act = 'disable';
    else
        act = 'enable';
    end if;

    for r in select c.relname from pg_namespace n
        join pg_class c on c.relnamespace = n.oid and c.relhastriggers = true
        where n.nspname = nsp
    loop
        execute format('alter table %I %s trigger all', r.relname, act); 
    end loop;
end;
$$
language plpgsql;
If you want to disable all triggers with certain trigger function it could be:

create or replace function disable_trigger_func(a boolean, f character varying) returns void as
$$
declare 
act character varying;
r record;
begin
    if(a is true) then
        act = 'disable';
    else
        act = 'enable';
    end if;

    for r in select c.relname from pg_proc p 
        join pg_trigger t on t.tgfoid = p.oid
        join pg_class c on c.oid = t.tgrelid
        where p.proname = f
    loop
        execute format('alter table %I %s trigger all', r.relname, act); 
    end loop;
end;
$$
language plpgsql;

also dosent work for me in Postgres 9.1. i use the two function described by bartolo-otrit with some modification. I modified the first function to make it work for me because the namespace or the schema must be present to identify the table correctly. The new code is :

CREATE OR REPLACE FUNCTION disable_triggers(a boolean, nsp character varying)
  RETURNS void AS
$BODY$
declare 
act character varying;
r record;
begin
    if(a is true) then
        act = 'disable';
    else
        act = 'enable';
    end if;

    for r in select c.relname from pg_namespace n
        join pg_class c on c.relnamespace = n.oid and c.relhastriggers = true
        where n.nspname = nsp
    loop
        execute format('alter table %I.%I %s trigger all', nsp,r.relname, act); 
    end loop;
end;
$BODY$
  LANGUAGE plpgsql VOLATILE
  COST 100;
ALTER FUNCTION disable_triggers(boolean, character varying)
  OWNER TO postgres;
then i simply do a select query for every schema :

SELECT disable_triggers(true,'public');
SELECT disable_triggers(true,'Adempiere');
           

https://github.com/digoal/blog/blob/master/201804/20180408_02.md#%E5%8F%82%E8%80%83 參考

https://www.postgresql.org/docs/devel/static/runtime-config-client.html#GUC-SESSION-REPLICATION-ROLE 《PostgreSQL rotate table 自動清理排程 - 限制,觸發器》 《PostgreSQL 事件觸發器應用 - DDL審計記錄 + 異步通知(notify)》 《資料入庫實時轉換 - trigger , rule》 《(流式、lambda、觸發器)實時處理大比拼 - 物聯網(IoT)\金融,時序處理最佳實踐》 《快速入門PostgreSQL應用開發與管理 - 7 函數、存儲過程和觸發器》 《PostgreSQL 10.0 preview 功能增強 - 觸發器函數内置中間表》 《PostgreSQL 安全陷阱 - 利用觸發器或規則,結合security invoker函數制造反噬陷阱》 《use PostgreSQL trigger manage stock & offer infomation》 《PostgreSQL trigger/rule based replication configure, DISABLE/ENABLE [ REPLICA | ALWAYS ] TRIGGER | RULE》 《PostgreSQL Oracle 相容性之 - 事件觸發器實作類似Oracle的資源回收筒功能》 《PostgreSQL 觸發器應用 - use trigger audit record which column modified, insert, delete.》 《use event trigger function record user who alter table's SQL》 《PostgreSQL 事件觸發器 - DDL審計 , DDL邏輯複制 , 打造DDL統一管理入》 《PostgreSQL 觸發器應用 - (觸發器WHEN)前置條件過濾跟蹤目标記錄》 《PostgreSQL 閃回 - flash back query emulate by trigger》 《PostgreSQL 事件觸發器 - PostgreSQL 9.3 Event Trigger》 《表級複制(base on trigger) -- PostgreSQL general sync and async multi-master replication trigger function》 《PostgreSQL 觸發器 用法詳解 2》 《PostgreSQL 觸發器 用法詳解 1》 《遞歸優化CASE - performance tuning case :use cursor\trigger\recursive replace (group by and order by) REDUCE needed blockes scan》 《PostgreSQL general public partition table trigger》 《表級複制(base on trigger) -- multi master replication & performance tuning》 《表級複制(base on trigger) -- one(rw) to many(ro|rw)》 《PostgreSQL 跟蹤DDL時間 - cann't use pg_class's trigger trace user_table's create,modify,delete Time》