ラブびあ

ビール。ときどきラブ

CSVファイルをsqlldrでロードする

WOWで動かすテンプレを使って、CSVファイルをsqlldrでロードするスクリプトを作ってみました。CSVファイルをsqlldr.vbsへドロップすると、CSVファイル名をテーブル名とみなしてORACLEデータベースの列情報からコントロールファイルを自動生成しsqlldrを起動します。CSVファイルとテーブルの列定義が異なる場合は、コントロールファイルの雛型作成ツールとして使えます。実行にあたっては、WOWで動かすテンプレのcmd.vbsとwow64.vbsが必要です。

sqlldr.vbs

option explicit

dim wsh,fso
const ForReading   = 1
const ForWriting   = 2
const ForAppending = 8

set wsh = CreateObject("Wscript.Shell")
set fso = CreateObject("Scripting.FileSystemObject")

include "cmd.vbs"
include "wow64.vbs"

dim OraSession
dim OraDatabase
dim OraDynaset

dim database
dim username
dim password

const ORADB_DEFAULT  = &H0&
const ORADYN_DEFAULT = &H0&
const ORAPARM_INPUT = 1

dim [ctl],[tbl],[dat],[log],[bat]

call init()
call main()
call fini()

set wsh = Nothing
set fso = Nothing

WScript.Quit


sub init()
	database = "orcl"
	username = "scott"
	password = "tiger"

	set OraSession  = CreateObject("OracleInProcServer.XOraSession")
	set OraDatabase = OraSession.OpenDatabase( _
									database, _
									username & "/" & password, _
									ORADB_DEFAULT)

	OraDatabase.Parameters.Add "table_name", 0, ORAPARM_INPUT
	OraDatabase.Parameters("table_name").AutoBindEnable
end sub

sub main()
	dim i
	for i = 0 to WScript.Arguments.Count - 1
		[dat] = WScript.Arguments(i)
		if fso.FileExists([dat]) then

			'入力ファイルパスからパラメータを決定する
			[tbl] = UCase(fso.GetBaseName([dat]))
			[ctl] = fso.BuildPath(fso.GetParentFolderName([dat]), tbl & ".ctl")
			[log] = fso.BuildPath(fso.GetParentFolderName([dat]), tbl & ".log")
			[bat] = fso.BuildPath(fso.GetParentFolderName([dat]), tbl & ".bat")

			call create_ctl() 'コントロールファイルを作成する
			call run_sqlldr() 'sqlldrを実行する
		end if
	next
end sub

sub fini()
	set OraDatabase = Nothing
	set OraSession  = Nothing
end sub

function create_ctl()
	'コントロールファイルを作成する
	dim f, sql
	set f = fso.OpenTextFile([ctl], ForWriting, True)

	f.WriteLine "OPTIONS("
	f.WriteLine "skip=1,"
	f.WriteLine "errors=-1"
	f.WriteLine ")"
	f.WriteLine "LOAD DATA"
	f.WriteLine "TRUNCATE INTO TABLE " & [tbl]
	f.WriteLine "FIELDS TERMINATED BY ','"
	f.WriteLine "OPTIONALLY ENCLOSED BY '""'"
	f.WriteLine "TRAILING NULLCOLS"
	f.WriteLine "("

	sql = "select column_name from user_tab_columns where table_name = :table_name order by column_id"
	OraDatabase.Parameters("table_name").Value = [tbl]

	set OraDynaset = OraDatabase.CreateDynaset(sql, ORADYN_DEFAULT)
	do until OraDynaset.EOF
		if OraDynaset.RowPosition > 1 then
			f.Write ","
		end if
		f.WriteLine OraDynaset.Fields(0).Value
		OraDynaset.MoveNext
	loop

	f.WriteLine ")"

	f.Close
	set f = Nothing
	set OraDynaset = Nothing
end function

function run_sqlldr()
	'SQLLDRを実行する
	wsh.Run cmd("SQLLDR [username]/[password]@[database] control='[ctl]' data='[dat]' log='[log]'")

	'SQLLDR実行コマンドをbatファイルへ出力する
	dim f
	set f = fso.OpenTextFile(bat, ForWriting, True)
	f.WriteLine cmd("SQLLDR [username]/[password]@[database] control='[ctl]' data='[dat]' log='[log]'")
	f.Close
	set f = Nothing
end function

sub include(filename)
	filename = fso.BuildPath(fso.GetParentFolderName(WScript.ScriptFullName), filename)
	ExecuteGlobal fso.OpenTextFile(filename, ForReading, False).ReadAll()
end sub