PostgreSQL で、一時的に全てのトリガーを無効にする

メモです。
(使用している PostgreSQL は PostgreSQL 9.3.12 です)

PostgreSQL で できるだけ他に影響を与えないように 一時的に全てのトリガーを無効にしたいと思っていたら 次のような方法がありました。

[参考]
PostgreSQLで一時的にtriggerを全て無効する方法 - Qiita

SET session_replication_role = replica;

クライアント接続の変数「session_replication_role」を変更する方法で この変数は、トリガおよびルールの発行を制御するそうです。

[参考]
18.11. クライアント接続デフォルト - PostgreSQL 9.3.2文書

実際に試してみます。

まず、table1 と table2 を作成。

CREATE TABLE table1 (
        field1  INTEGER
,       field2  INTEGER
);

CREATE TABLE table2 (
        field1  INTEGER
);

table1 の INSERT 時に field1 の値を field2 にセットする BEFORE トリガーを作成。

CREATE FUNCTION before_func1()
RETURNS TRIGGER AS $$
BEGIN
    NEW.field2 := NEW.field1;
    RETURN NEW;
END;
$$ LANGUAGE 'plpgsql';

CREATE TRIGGER before_trigger1
    BEFORE INSERT ON table1
    FOR EACH ROW EXECUTE PROCEDURE before_func1();

table1 の INSERT 時に table2 にレコードを INSERT する AFTER トリガーを作成。

CREATE FUNCTION after_function1()
RETURNS TRIGGER AS $$
BEGIN
    INSERT INTO table2 (field1) VALUES (NEW.field1);
    RETURN NULL;
END;
$$ LANGUAGE 'plpgsql';

CREATE TRIGGER after_trigger1
    AFTER INSERT ON table1
    FOR EACH ROW EXECUTE PROCEDURE after_function1();

テーブルとトリガーを作成したら、次の SQL を実行します。

INSERT INTO table1 (field1) VALUES (1);

table1 に INSERT 。

db=# INSERT INTO table1 (field1) VALUES (1);

INSERT 0 1

table1 を確認。

db=# SELECT * FROM table1;

 field1 | field2
--------+--------
      1 |      1
(1 row)

BEFORE トリガーで field2 に値がセットされています。

table2 を確認。

db=# SELECT * FROM table2;

 field1
--------
      1
(1 row)

AFTER トリガーで レコードが INSERT されています。

次にクライアント接続の変数「session_replication_role」を試しますが まず初期値を確認。

db=# SHOW session_replication_role;

 session_replication_role
--------------------------
 origin
(1 row)

初期値は「origin」でした。

クライアント接続の変数「session_replication_role」に 「replica」を設定します。

db=# SET session_replication_role = replica;

SET
db=# SHOW session_replication_role;

 session_replication_role
--------------------------
 replica
(1 row)

ちゃんと変更されてます。

さっきと同じ INSERT 文を実行。
(テーブルのレコードはクリア済です)

db=# INSERT INTO table1 (field1) VALUES (1);

INSERT 0 1

table1 を確認。

db=# SELECT * FROM table1;

 field1 | field2
--------+--------
      1 |
(1 row)

BEFORE トリガーが実行されなかったため field2 に値がセットされていません。

table2 を確認。

db=# SELECT * FROM table2;

 field1
--------
(0 rows)

AFTER トリガーが実行されなかったため レコードが INSERT されていません。

トリガーは実行されませんでした。
これは便利ですね。

もちろん他のセッションでは通常通りの動作をします。

ただし、整合性が保たれなくなる可能性があるので 当然ながら慎重に実行する必要があります。

Google サイト内検索

Amazonアソシエイト