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 と table 2 を作成。

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 されていません。

これは便利ですね。

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

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

Windows で システム エラー 1219 が消えないときの対処A

メモです。
(使用している Windows は Windows 10 です)

前に「システム エラー 1219 が消えないときの対処@」を書きましたが 今回は「システム エラー 1219」が発生したときに 「とりあえず、ここも見ておこう」という内容です。

まず NET USE をしますが 出てこないから困るわけです。

C:\> NET USE

新しい接続は記憶されません。

一覧にエントリが存在しません。

こういうときは 次の場所もチェックしてみます。

「コントロールパネル」から「ユーザアカウント」を選択。

WRITE_0897_02

「資格情報の管理」をクリック。

右側にある「Windows 認証情報」をクリック。

WRITE_0897_03

接続しようとしているサーバの情報が表示されたら そのせいで「システム エラー 1219」が出ている可能性があります。

削除して問題なければ「削除」をクリック。

この情報はサーバ接続時に「資格情報を記憶する」にチェック入れると 登録されます。

WRITE_0897_01

削除して問題なければ「削除」をクリック。

これで「システム エラー 1219」が消えることがあります。

差分ファイルだけを tar コマンドで固める

メモです。
(使っている Linux は Ubuntu 14.04.3 LTS です)

find コマンドで取得した更新日が新しいファイルだけを tar コマンドで 固める方法です。

更新日は、比較対象のファイルより新しいものを取得します。 (この方法については、前に書いているので、そちらを参照してください)

まずは環境変数の設定。
比較対象のファイル(BASE_FILE_PATH)と 固めるTARファイル(TAR_FILE_PATH)のパスを設定します。

$ BASE_FILE_PATH=./last_update.txt
$ TAR_FILE_PATH=/tmp/xxxxxx

既存のTARファイルが存在するとよろしくないため 念のためですが、0バイトで上書きしておきます。

$ cat /dev/null > ${TAR_FILE_PATH}.tar

find コマンドでファイルを取得しつつ tar コマンドで固めます。 このとき、tar コマンドでは 追記 "r" を指定するのと 圧縮の "z" は指定しないようにします。

$ find ./ -type f -newer ${BASE_FILE_PATH} -exec tar rf ${TAR_FILE_PATH}.tar {} \;

TAR ボールを作った後で圧縮します。

$ gzip -f ${TAR_FILE_PATH}.tar

最後に比較対象のファイルを touch コマンドで更新しておけば 次もこの後からの差分を取得することができます。

$ touch ${BASE_FILE_PATH}

Windows 上で .htaccess のようなファイルを作成する

(使用している Windows は Windows 10 です)

Windows 上で普通に .htaccess のような「 . (ドット)」 から始まるファイルを作成しようとすると 拡張子のみと判断されて 次のようにエラーが出てしまいます。

WRITE_0894_01

最近知ったのですが、そういうときは 次のようにファイル名の最後にも「 . 」を入れます。

WRITE_0894_02

そうすると 最後の「 . 」は消えて .htaccess になります。

WRITE_0894_03

これはフォルダなどでも同じです。

この方法だと コマンドプロンプトや他の方法を使わなくても 簡単に「 . 」から始まるファイルを作ることができます。

Windows で システム エラー 1219 が消えないときの対処@

メモです。
(使用している Windows は Windows 10 です)

次のようにネットワークドライブの割り当てをしようとしたときに 「システム エラー 1219」が発生することがあります。

C:\> NET USE P: \\fileserver ...
システム エラー 1219 が発生しました。
同じユーザーによる、サーバーまたは共有リソースへの複数のユーザー名での複数の接続は許可されません。
サーバーまたは共有リソースへの以前の接続をすべて切断してから、再試行してください。

たいていは NET USE ... /DELETE で解決しますが たまにエラーが消えないときがあります。

NET USE で見ても一覧に表示されず。

C:\> NET USE

新しい接続は記憶されません。

一覧にエントリが存在しません。

こんなとき、とりあえずの対処法として 次のようにサーバ名をIPアドレス(または逆にIPアドレスからサーバ名)に変更して コマンドを実行します。

C:\> NET USE P: \\192.168.1.200 ...

サーバ名が設定されていない場合は 自分のパソコンの lmhosts などに記載すると良いです。

find コマンドで日時を指定して検出する

メモです。
(使っている Linux は Ubuntu 14.04.3 LTS です)

find コマンドで -mtime オプションを使うと ファイルの更新日を条件にして「〜日前」のような検出ができます。

$ find ./ -mtime -3

具体的に日時を指定して検出するには 次のように -newermt オプションを使用します。 (-newermt の m は Modify の m で、a にすると Access、c だと Change になります)

$ find ./ -newermt "2018/10/30 12:00"

(日付の書式は色々指定できます)

これで指定した時刻よりもタイムスタンプが大きい(指定した時刻は含まれない)ファイルを検出することができます。

-newerXY reference

    Compares the timestamp of the current file with reference.  The reference argument is normally the name
    of a file (and one of its timestamps is used for the comparison) but it may also be a string describing
    an absolute time.  X and Y are placeholders for other letters, and  these  letters  select  which  time
    belonging to how reference is used for the comparison.

    a   The access time of the file reference
    B   The birth time of the file reference
    c   The inode status change time of reference
    m   The modification time of the file reference
    t   reference is interpreted directly as a time

    Some  combinations  are  invalid;  for example, it is invalid for X to be t.  Some combinations are not
    implemented on all systems; for example B is not supported on all systems.  If  an  invalid  or  unsup‐
    ported  combination  of XY is specified, a fatal error results.  Time specifications are interpreted as
    for the argument to the -d option of GNU date.  If you try to use the birth time of a  reference  file,
    and  the  birth  time cannot be determined, a fatal error message results.  If you specify a test which
    refers to the birth time of files being examined, this test will fail for any  files  where  the  birth
    time is unknown.

find コマンドで特定のファイル以降の更新を検出する

メモです。
(使っている Linux は Ubuntu 14.04.3 LTS です)

find コマンドで -mtime オプションを使うと ファイルの更新日を条件にして「〜日前」のような検出ができます。

$ find ./ -mtime -3

何かの作業で更新したファイル以降に作成・更新されたファイルを検出したい場合 -newer というオプションが使えます。

$ find ./ -newer hogehoge.txt
-newer file

    File  was  modified  more  recently  than file.  If file is a symbolic link and the -H option or the -L
    option is in effect, the modification time of the file it points to is always used.

このオプションは、引数のファイルのタイムスタンプよりタイムスタンプが新しいファイルを検出してくれます。

引数のファイルのタイムスタンプ“より大きい”ため、そのファイル自体は含まれません。 引数のファイルが対象の中にあっても、検出されないようになってるわけです。 よく考えられてますね。

ORACLE で実行した SQLから実行計画を表示する

ORACLE で実行計画を表示したい状況があったのですが 自由にテーブルを作れる環境ではなく どうしようかと思っていたところ、 実行したSQLに対して実行計画を表示する方法がありました。

次のように「DBMS_XPLAN.DISPLAY_CURSOR」を使用します。

SQL> SELECT * FROM TABLE(DBMS_XPLAN.DISPLAY_CURSOR());

最後に実行したSQLの実行計画が次のように表示されます。

PLAN_TABLE_OUTPUT
--------------------------------------------------------------------------------
SQL_ID  dyk4dprp70d74, child number 0
-------------------------------------
SELECT DECODE('A','A','1','2') FROM DUAL

Plan hash value: 1388734953

-----------------------------------------------------------------
| Id  | Operation        | Name | Rows  | Cost (%CPU)| Time     |
-----------------------------------------------------------------
|   0 | SELECT STATEMENT |      |       |     2 (100)|          |
|   1 |  FAST DUAL       |      |     1 |     2   (0)| 00:00:01 |

PLAN_TABLE_OUTPUT
--------------------------------------------------------------------------------
-----------------------------------------------------------------

ただ、DISPLAY_CURSOR の実行には「V$SQL_PLAN、V$SESSIONおよびV$SQL_PLAN_STATISTICS_ALL.の各固定ビューに対するSELECT権限が必要です。」とのことです。

[参考]
DBMS_XPLAN - OracleR Database PL/SQLパッケージおよびタイプ・リファレンス

実行したSQLを指定するには、 V$SQL で SQL_ID を調べて 以下のように実行します。

SQL> SELECT * FROM TABLE(DBMS_XPLAN.DISPLAY_CURSOR('SQL_ID'));

実行したSQLにしか使えませんが テーブル等を作らなくて良いのは助かります。

tar コマンドでパスを変更して展開したい

メモです。
(使っている Linux は Ubuntu 14.04.3 LTS です)

tar コマンドで展開するときに 格納されているパスがそのまま使えずに パスの一部を変更して展開したいときがあります。

[格納されているパス]
home/hogehoge/test1/xxxxxx

[展開したいパス]
/home/hogehoge/test2/xxxxxx

次のようにオプションと変更内容を指定することで、 パスを変更しながら展開することができます。

$tar xzvf xxxxx.tar.gz --transform='s/test1/test2/g'
File name transformations:

    --transform=EXPRESSION, --xform=EXPRESSION
                           use sed replace EXPRESSION to transform file
                           names

ディレクトリの「 / 」も変更したい場合は 次のように区切り文字を「 | 」などに変更しておくと良いと思います。

$tar xzvf xxxxx.tar.gz --transform='s|hogehoge/test1|hugahuga/test2|g'

tar コマンドで一部だけを展開したい

メモです。
(使っている Linux は Ubuntu 14.04.3 LTS です)

tar コマンドで展開するときに 特定のファイルや、特定のディレクトリ以下のファイルだけを展開したいときがあります。

次のようにパスを指定することで、そのファイルだけを展開することができます。

$ tar xvzf xxxxx.tar.gz home/hogehoge/test.html

同様に、ディレクトリのパスを指定すると、そのディレクトリ以下を展開できます。

$ tar xvzf xxxxx.tar.gz home/hogehoge

パスの指定にはワイルドカードを使うこともできます。

$ tar xvzf xxxxx.tar.gz --wildcards */hogehoge.png
File name matching options (affect both exclude and include patterns):

    --wildcards            use wildcards (default for exclusion)
    --no-wildcards         verbatim string matching

余談ですが、TABキーの入力補完で .tar.gz ファイルの中のパスまで 指定できてビックリしました。

Google サイト内検索

Amazonアソシエイト