Help us understand the problem. What is going on with this article?

【PostgreSQL】WSH/VBScriptでpsqlを使用する

はじめに

Windowsサーバーリプレース作業にて、データベースを Oracle 11g から PostgreSQL 9.6 に移行作業をしています。
OracleのSQLPlusと違って、psqlだとパスワードを指定するオプションがないので不便ですね。

パスワード認証を省略

2通りの方法があります。

pgpass.conf

パスワード入力なしでpsqlを実行するには、下記フォルダの「pgpass.conf」にパスワードを設定しておく。
%APPDATA%\postgresql\pgpass.conf
※pgpass.confは、postgresのdataフォルダに置くものではありません。
※pgpass.confは、UTF-8(BOM無し)で保存・作成してください。

pgpass.conf
#hostname:port:database:username:password
localhost:5432:*:postgres:(パスワード)

環境変数(PGPASSWORD)

セキュリティ上は非推奨であるがバッチ内に環境変数(PGPASSWORD)を設定した上で実行する。

SET PGPASSWORD=(パスワード)
psql -U (ユーザー) -f xxxxx.sql 

WSH/VBScriptで実行

pgpass.conf のユーザーであればパスワードを省略できるので、SET PGPASSWORDは不要ですが、指定以外のユーザーではパスワードを要求されます。

VBS上でSET変数を入れて実行するには、"CMD /C SET "を使用するのですが、PGPASSWORDに関しては簡単に行かなかった。
試行錯誤してコマンドプロンプトにてワンライナーで下記のようにすると実行できるようになりました。

CMD /C SET "PGPASSWORD=fuga" ^& "C:\PostgreSQL\9.6\bin\psql.exe" -h localhost -U test -d postgres -c "SELECT now()"

これならVBSで実行できるのではないかと組んだわけですが、結果は何も出力されない。

Option Explicit
Dim objShell, cmd

Set objShell = CreateObject("WScript.Shell")

cmd = "CMD /C SET ""PGPASSWORD=fuga"" ^& ""C:\PostgreSQL\9.6\bin\psql.exe"""
cmd = cmd & " -h localhost"
cmd = cmd & " -U test"
cmd = cmd & " -d postgres"
cmd = cmd & " -c ""SELECT now()"""

WScript.Echo objShell.Exec(cmd).StdOut.ReadAll
Set objShell = Nothing

無理矢理、なんとかしてみようと考えました。
バッチファイルを一時的に生成して実行することで、結果が表示されるようになります。

Option Explicit
Dim objShell, fso, cmd, objFile

const BAT_NAME = "tmp.bat"

Set objShell = CreateObject("WScript.Shell")
Set fso = WScript.CreateObject("Scripting.FileSystemObject")

cmd = "SET PGPASSWORD=fuga" & vbCrlf
cmd = cmd & """C:\PostgreSQL\9.6\bin\psql.exe"""
cmd = cmd & " -h localhost"
cmd = cmd & " -U test"
cmd = cmd & " -d postgres"
cmd = cmd & " -c ""SELECT now()"""
Set objFile = fso.OpenTextFile(BAT_NAME, 2, True)
objFile.WriteLine cmd
objFile.Close

WScript.Echo objShell.Exec(BAT_NAME).StdOut.ReadAll
fso.DeleteFile BAT_NAME, True

' オブジェクトを開放する
Set fso = Nothing
Set objFile = Nothing
Set objShell = Nothing

SQLの実行方法

psqlのcオプションで指定する。

cmd = cmd & " -c ""SELECT now()"""

psqlのfオプションで外部スクリーンを指定する。

cmd = cmd & " -f test.sql"

StdIn.Writeでsqlを指定する。

sql = "SELECT now()"

Set objShell = CreateObject("WScript.Shell")
With objShell.Exec(cmd)
    .StdIn.Write sql
    .StdIn.Close
    WScript.Echo .StdOut.ReadAll
End With

psqlを使わない

VBScriptを使うならADOが使えます。これなら普通にパスワードを指定できるよね。
ODBCデータソースアドミニストレーターの設定で"PostgreSQL35W"をしておく。

PostgreSQLの接続確認

'初期化処理
Option Explicit
On Error Resume Next
Dim Conn, RS

'DB接続
Set Conn = WScript.CreateObject("ADODB.Connection")
Conn.Open "DSN=PostgreSQL35W;UID=test;PWD=fuga"
Set RS = Conn.Execute("SELECT 'Connect OK'")

If RS.Eof Then
    WScript.Echo 1    '接続エラ-
Else
    WScript.Echo 0    '接続OK
End If

RS.Close
Conn.Close
Set RS = Nothing
Set Conn = Nothing

最後に

監視用にOracleのSQLPlusを使用していたプログラムの移植ってことでpsqlの使用を考えていたのですが、ものによってはADOを使用しても問題ないわけです。
ここらへんは柔軟に変更していくことも考えてみる。

yaju
静岡県島田市在住のシニアSEがコンピューター、機械学習、Unity、数学について考える
http://yaju3d.hatenablog.jp/
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした