自力理解ができないので?@ITに投稿してみました^^;
現象
パラメータを使用して複数件のデータをOracleデータベースに更新する際、パラメータのDbTypeを設定せずに更新クエリーを実行するとOracleExceptionがThrowされる場合があります。
例えば、OracleテーブルのDate型フィールドに2件のデータを登録するとします。
1件目のデータがNowであれば更新クエリーは成功します。
1件目:Now
2件目:DbNull.Value
1件目のデータがDbNull.Valueであれば更新クエリーは2件目のデータを更新する際にOracleExceptionをThrowします。
1件目:DbNull.Value
2件目:Now
ThrowするException
ORA-01861: リテラルが書式文字列と一致しません。
パラメータのDbTypeを設定すれば例外はThrowされません。
SQLServerでは発生しないようです。
サンプルコード
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
'データテーブルオブジェクトを作成します。
Dim table As New DataTable
table.Columns.Add(New DataColumn("TESTDATE", GetType(Date)))
Dim row As DataRow
'データテーブルに1件目のデータを追加します。
row = table.NewRow
row("TESTDATE") = DBNull.Value
table.Rows.Add(row)
'データテーブルに2件目のデータを追加します。
row = table.NewRow
row("TESTDATE") = Now
table.Rows.Add(row)
'コネクションオブジェクトを作成します。
Dim cnn As New OracleClient.OracleConnection
cnn.ConnectionString = "接続文字列"
'コマンドオブジェクトを作成します。
Dim cmdInsert As New OracleClient.OracleCommand
cmdInsert.Connection = cnn
cmdInsert.CommandText = "INSERT INTO TESTTABLE (TESTDATE) VALUES (:TESTDATE)"
'パラメータを作成します。
Dim prm As New OracleClient.OracleParameter
prm = cmdInsert.CreateParameter
'--DbTypeを指定しないとExceptionが発生します。--
prm.DbType = DbType.Date
prm.ParameterName = "TESTDATE"
prm.SourceColumn = "TESTDATE"
cmdInsert.Parameters.Add(prm)
'データテーブルの変更をデータベースへ反映します。
Dim adp As New OracleClient.OracleDataAdapter
adp.InsertCommand = cmdInsert
adp.Update(tbl)
End Sub
MSDNでOracleParameter.DbType プロパティを確認すると
パラメータの DbType プロパティ、OracleType プロパティ、および.Data.OracleClient.OracleParameter.Size プロパティは、.Data.OracleClient.OracleParameter.Value を設定することによって推論できます。したがって、これらを指定する必要はありません。とありました。
パラメータはValue値からDbTypeを推論します。
Oracle® Data Provider for .NET開発者ガイド の「ValueからのDbTypeおよびOracleDbType」の推論によると.Netデータ型がDateTimeのときOracleDbTypeはTimeStampを推論するようです。
つまり1件目のデータのパラメータValue値がDbNull.Valueの場合、OracleDbTypeをTimeStampと推論し2件目のデータでOracleDbTypeがDate型のデータをInsertしようとして例外がスローされるようです。
1件目のデータのパラメータValue値がDbNull.Value以外であればOracleDbTypeはDate型を推論するため、1件目のデータがNowであれば例外はスローされないということのようです。
0 件のコメント:
コメントを投稿