指定ディレクトリ以下のファイルを全てSQL*Plusで実行するスクリプト

' 指定ディレクトリ以下の*.sql, *.spc, *.bdyファイルを全てSQL*Plusで実行します。
'
' USAGE:
' CScript ExecAllFileAtSQLPlus.vbs [/PATH:処理を開始するディレクトリ] [/CONN:接続文字列] [/RECURCIVE:[True or False]]
'     PATH      : 処理を開始するディレクトリをフルパスで指定します。指定しない場合はカレントディレクトリを起点として処理を開始します。
'     CONN      : Oracleの接続文字列を指定します。指定しない場合は入力用のInputBoxが表示されます。
'     RECURCIVE : サブディレクトリに対して再帰的に処理を行うかどうかを指定します(TrueまたはFalse)。指定しない場合はサブディレクトリも処理します。(Trueと同義)
'     SILENT    : SQL*Plusをサイレントオプション付きで起動します。

Option Explicit

' SQLPlusのパス。ここは環境に合わせて変える。
Const SQL_PLUS_PATH="D:\app\foohogehoge\product\11.2.0\ODAC112011\sqlplus.exe"

' 既定の接続文字列
const DEFAULT_CONN_STR="scott/tiger@northwind"

' タイムアウト時間(ms)。0でタイムアウトなし。
const WAIT_TIME=0


Dim objWshShell:Set objWshShell = WScript.CreateObject("WScript.Shell")
Dim objFileSystem:Set objFileSystem = CreateObject("Scripting.FileSystemObject")

If (WScript.Arguments.Named.Exists("HELP") or WScript.Arguments.Named.Exists("?")) Then
    WScript.Echo("CScript ExecAllFileAtSQLPlus.vbs [/PATH:処理を開始するディレクトリ] [/CONN:接続文字列] [/RECURCIVE:[True or False]] [/S[ILENT]]")
    WScript.Echo("指定ディレクトリ以下の*.sql, *.spc, *.bdyファイルを全てSQL*Plusで実行します。")
    WScript.Echo("")
    WScript.Echo("    PATH      : 処理を開始するディレクトリをフルパスで指定します。")
    WScript.Echo("                指定しない場合はカレントディレクトリを起点として処理を開始します。")
    WScript.Echo("")
    WScript.Echo("    CONN      : Oracleの接続文字列を指定します。指定しない場合は入力用のInputBoxが表示されます。")
    WScript.Echo("")
    WScript.Echo("    RECURCIVE : サブディレクトリに対して再帰的に処理を行うかどうかを指定します(TrueまたはFalse)。")
    WScript.Echo("                指定しない場合はサブディレクトリも処理します。(Trueと同義)")
    WScript.Echo("")
    WScript.Echo("    SILENT    : SQL*Plusをサイレントオプション付きで起動します。")
    WScript.Quit(0)
End If

Dim silent
If (WScript.Arguments.Named.Exists("SILENT") or WScript.Arguments.Named.Exists("S")) Then
    silent = true
Else
    silent = false
End If

' 処理開始ディレクトリの取得
Dim rootDirPath
If (WScript.Arguments.Named.Exists("PATH")) Then
    ' 引数指定時は指定されたパスから処理開始
    rootDirPath = WScript.Arguments.Named.Item("PATH")
Else
    ' 引数なしのときはカレントディレクトリから処理開始
    rootDirPath = objWshShell.CurrentDirectory
End If

' 接続文字列の取得
Dim connectionString
If (WScript.Arguments.Named.Exists("CONN")) Then
    ' 引数指定時は指定された接続文字列を使用
    connectionString = WScript.Arguments.Named.Item("CONN")
Else
    ' 引数なしのときは接続文字列の入力を促す
    connectionString = InputBox(rootDirPath & " 以下のSQLファイルを実行します。" & Chr(13) & "接続文字列を指定してください。", "SQL実行", DEFAULT_CONN_STR)
End If

' サブディレクトリを再帰処理するかどうかを取得
Dim recurcive
If (WScript.Arguments.Named.Exists("RECURCIVE")) Then
    recurcive = CBool(WScript.Arguments.Named.Item("RECURCIVE"))
Else
    recurcive = True
End If

Main(rootDirPath)

WScript.Echo "Enterキーを押すと終了します"
strInp = WScript.StdIn.ReadLine

Function Main(rootDirPath)
    Call ExecSQL(rootDirPath, "SPC")
    Call ExecSQL(rootDirPath, "BDY")
    Call ExecSQL(rootDirPath, "SQL")
End Function

Sub ExecSQL(rootDirPath, ext)
    Dim root:Set root = objFileSystem.GetFolder(rootDirPath)

    ' サブフォルダを持っていれば再起処理
    if (recurcive = True) Then
        Dim subdir
        For Each subdir in root.SubFolders
            Call ExecSQL(subdir.Path, ext)
        Next
    End If


    Dim file
    Dim progress
    For Each file in root.Files
        If (UCase(objFileSystem.GetExtensionName(file.Path)) = ext) Then
            ' そのままではSQLPlusが終了しないので、末尾にquitを付けるなど編集した一時SQLファイルを作成
            Dim tempFile:tempFile = objFileSystem.GetTempName()
            Dim tempFileSQL:tempFileSQL = objWshShell.ExpandEnvironmentStrings("%TEMP%") & "\\" & tempFile

            Dim objTempSQL:Set objTempSQL = objFileSystem.CreateTextFile(tempFileSQL, true)
            objTempSQL.WriteLine("SET LINESIZE 20000;")
            objTempSQL.WriteLine("SET SQLBLANKLINES ON;")
            objTempSQL.WriteLine("pro &_USER@&_CONNECT_IDENTIFIER;")
            objTempSQL.WriteLine("start """ & file.Path & """;")
            objTempSQL.WriteLine("show errors;")
            objTempSQL.WriteLine("quit;")

            WScript.Echo("■" & file.Path & " を実行します。")
            'WScript.Echo("一時ファイル名 " & tempFileSQL)

            Dim result
            Dim sqlPlusOption:sqlPlusOption = " "
            If (silent = true) Then
                sqlPlusOption = sqlPlusOption & "-S "
            End If
            Set result = objWshShell.Exec(SQL_PLUS_PATH & sqlPlusOption & connectionString & " @" & tempFileSQL)
            Dim WaitCount:WaitCount = 0
            Dim Interval:Interval  = 100
            Do While result.Status = 0
                ' WScript.StdOut.Write(".")
                WScript.Sleep Interval
                WaitCount = WaitCount + 1
                If (WaitCount Mod 10 = 0) Then
                    if(Len(progress) <> 0) then
                        WScript.StdOut.Write(String(Len(progress),ChrW(8)))
                    End If
                    progress = WaitCount * Interval & "ms"
                    WScript.StdOut.Write(progress)
                End If
                If (WAIT_TIME > 0 and (WaitCount * Interval) > WAIT_TIME) Then
                    WScript.StdOut.WriteLine("タイムアウトしました。")
                    result.Terminate
                    Exit Do
                End If
            Loop
            WScript.Echo()
            WScript.Echo(result.StdOut.ReadAll)
            WScript.Echo(result.StdErr.ReadAll)

            objTempSQL.Close()
            call objFileSystem.DeleteFile(tempFileSQL, true)
        End If
    Next
End Sub