社内SEの徒然なる日記

powerShellからOracleを使う(トランザクション)

PowerShellでトランザクション

powerShellからOracleに接続してトランザクション制御を行ってみます。
今回で、PowerShellからのOracle操作シリーズは最終回にします。

トランザクションの使い方(概要)

先に、実装の概要だけ書いておきます。

まず、oracleConectionクラスのBeginTransactionメソッドでトランザクションを開始します。
このメソッドは戻値として、新しいトランザクションを表すOracleTransactionオブジェクトを返します。

このオブジェクトを、oracleCommandクラスのTransactionプロパティに設定します。
これによって、oracleCommandオブジェクトから実行されるSQLがトランザクション制御されるようになります。

コミットやロールバックは、OracleTransactionオブジェクトで実行します。
コミットであれば、Commitメソッドを、ロールバックであれば、Rollbackメソッドを使用します。
...そのまんまですね。

トランザクションは、これ以外の方法でも実現できそうですが、MSDNライブラリのOracleConnection.BeginTransaction メソッドの説明には、使わないでくれって書いてあります。
そう言われると、やってみたくなるのが人情ですが、面倒なのでやめておきます。

サンプルコード

トランザクションを利用して、INSERT文を2回発行するサンプルです。

# OracleClientのアセンブリをロード
[void][System.Reflection.Assembly]::LoadWithPartialName("System.Data.OracleClient")

# OracleConnectionオブジェクトの作成
$oracleConectionString = "Data Source=TESTDB;User ID=USER01;Password=USER001;Integrated Security=false;"
$oracleConection = New-Object System.Data.OracleClient.OracleConnection($oracleConectionString)
$oracleCommand = New-Object System.Data.OracleClient.OracleCommand
$oracleCommand.Connection = $oracleConection

# データベースに接続します。
$oracleConection.Open()


# トランザクションを開始します。
$oracleTransaction = $oracleConection.BeginTransaction()

# トランザクションを設定します。
$oracleCommand.Transaction = $oracleTransaction

try {

# SQL(INSERT文)を実行します。
$oracleCommand.CommandText = "INSERT INTO ABCD (TESTCD, TESTID) VALUES ('0', '000')"
[void]$oracleUpdateCount = $oracleCommand.ExecuteNonQuery()

# SQL(INSERT文)を実行します。
$oracleCommand.CommandText = "INSERT INTO ABCD (TESTCD, TESTID) VALUES ('0', '001')"
[void]$oracleUpdateCount = $oracleCommand.ExecuteNonQuery()

# コミットします。
$oracleTransaction.Commit()
Write-Host "コミットしました。"

} catch [Exception] {

# ロールバックします。
$oracleTransaction.Rollback()

Write-Host "トランザクションエラー(ロールバック)"
$Error[0]
}


# DB切断&リソース解放。
$oracleCommand.Dispose()
$oracleConection.Close()
$oracleConection.Dispose()


サンプルの解説


1.トランザクションの開始と設定

最初に開設した通り、oracleConection.BeginTransaction()でトランザクションを開始して、oracleCommand.Transactionプロパティに開始したトランザクションを設定します。

2.エラートラップ

当然の話ですが、正常時はコミット、異常時はロールバックをさせるためにエラートラップを仕込みます。
try {処理、コミット} catch [Exception] {ロールバック} って感じですかね。

あらゆるエラーを拾うため、catchする例外はExceptionにしておきます。

3.コミット&ロールバック

$oracleTransaction.Commit() でコミット、$oracleTransaction.Rollback() でロールバックです。
見ての通りなので、これ以上書くこともないですね。

コミットもロールバックもしないとどうなる?

コミットもロールバックもされずに処理を終了した場合、自動的にロールバックが実行されるようです。

だからと言って、ロールバックを書かなくても良いって事じゃないですよ。
作法として、きちんとエラートラップして、ロールバックを発行して下さい。
でないと、思わぬ障害の原因になります。

トランザクション終了後にDML文を発行すると...

トランザクション終了後に、さらにDML文を発行してみます。
こんな感じですね。

$oracleTransaction = $oracleConection.BeginTransaction()
$oracleCommand.Transaction = $oracleTransaction

try {
# SQL(INSERT文)を実行します。
$oracleCommand.CommandText = "INSERT INTO ABCD (TESTCD, TESTID) VALUES ('0', '000')"
[void]$oracleUpdateCount = $oracleCommand.ExecuteNonQuery()
$oracleCommand.CommandText = "INSERT INTO ABCD (TESTCD, TESTID) VALUES ('0', '001')"
[void]$oracleUpdateCount = $oracleCommand.ExecuteNonQuery()

$oracleTransaction.Commit()
} catch [Exception] {
$oracleTransaction.Rollback()
}


# SQL(INSERT文)を実行します。
$oracleCommand.CommandText = "INSERT INTO ABCD (TESTCD, TESTID) VALUES ('0', '003')"
[void]$oracleUpdateCount = $oracleCommand.ExecuteNonQuery()



既にトランザクションが終了されているので、最後のINSERT文は、即座にコミットされてしまいます。
それでは問題あるという場合は、もう一度トランザクションを開始してやります。

トランザクションを再開する

1つの処理で複数のトランザクション制御が必要な場合の方法です。

# 1回目のトランザクション
$oracleTransaction = $oracleConection.BeginTransaction()
$oracleCommand.Transaction = $oracleTransaction

try {
# SQL(INSERT文)を実行します。
$oracleCommand.CommandText = "INSERT INTO ABCD (TESTCD, TESTID) VALUES ('0', '000')"
[void]$oracleUpdateCount = $oracleCommand.ExecuteNonQuery()
$oracleCommand.CommandText = "INSERT INTO ABCD (TESTCD, TESTID) VALUES ('0', '001')"
[void]$oracleUpdateCount = $oracleCommand.ExecuteNonQuery()

$oracleTransaction.Commit()
} catch [Exception] {
$oracleTransaction.Rollback()
}


# 2回目のトランザクション
$oracleTransaction = $oracleConection.BeginTransaction()
try {
# SQL(INSERT文)を実行します。
$oracleCommand.CommandText = "INSERT INTO ABCD (TESTCD, TESTID) VALUES ('0', '003')"
[void]$oracleUpdateCount = $oracleCommand.ExecuteNonQuery()

$oracleTransaction.Commit()
} catch [Exception] {
$oracleTransaction.Rollback()
}



見ての通り、一連の処理をもう一度実行するだけですけどね。
ただし、oracleCommandのTransactionプロパティへの設定は、最初の1回だけでOKです。

余談ですが、$oracleConection.BeginTransaction() を実行せずにコミットやロールバックを行うと、異常終了します。

前回:powerShellからOracleを使う(DML文:INSERT、UPDATE、DELETE)
投稿記事の一覧:目次

後書き

これで、使いそうな機能の紹介は終了になります。
自分用の備忘録なのですが、どなたかのお役に立てたのなら幸いです。

実際には、もっと多くの機能があるのですが、多すぎてついていけませんし、これ以上の機能を使って実装すると、他の人が付いていけなくなりそうです。
熟練したエンジニアが沢山いる会社に居るのなら、難しい機能を使ってもいいのかもしれませんが、中小企業のシステム部門では人の確保も中々難しいです。

結局は、私のように練度の低い人でも何とか使える機能しか使えないんですよね。
まぁ、無理に難しい機能を使う必要もないっていうのもありますけどね。
スポンサードリンク

PageTop

コメント


管理者にだけ表示を許可する