- PR -

oracle.data.adapterで自動生成されるSQLについて

投稿者投稿内容
VB初心者
常連さん
会議室デビュー日: 2008/09/29
投稿数: 20
投稿日時: 2008-09-30 17:05
VB2005、Oracle共に初心者です。

oracle.data.adapterでSQLを自動生成し、テーブルを更新する
処理を作成しております。(System.Data.OracleClientにより
Access MDBを更新するプログラムをOracle用に変更中)

実際に実行したところ、「ORA-00911: 文字が無効です。」の
エラーが発生しました。

原因を探りたいのですが、自動生成されたSQL文の内容を確認
するには、どのようにすれば良いのでしょうか?

とりあえず、ソースも記載しておきますので、何か気づいた方が
いらっしゃれば、アドバイスも含めてお願いします。

【ソースコード(途中省略】
' UPDATEコマンドの作成
Private Function CreateUpdateCommand(ByVal dt As DataTable, ByVal AddTablename As Boolean) As OracleCommand
Dim cmd As New OracleCommand
Dim SqlStr As String
Dim i As Integer

cmd.CommandText = "UPDATE " & dt.TableName & " SET "
i = 1
SqlStr = ""
For Each col As DataColumn In dt.Columns
If AddTablename = True Then
SqlStr = SqlStr & dt.TableName & "." & col.ColumnName & " = ?, "
Else
SqlStr = SqlStr & col.ColumnName & " = ?, "
End If

Dim param As New OracleParameter
param.ParameterName = "@p" & i
param.SourceColumn = col.ColumnName
If col.DataType Is System.Type.GetType("System.String") Then
param.OracleDbType = OracleDbType.Varchar2
Else
param.OracleDbType = OracleDbType.Int32
End If
param.SourceVersion = DataRowVersion.Current
cmd.Parameters.Add(param)
Next

' 最後に付加したカンマを破棄
cmd.CommandText = cmd.CommandText & Left(SqlStr, Len(SqlStr) - 2) & " WHERE "

SqlStr = ""
i = 1
For Each col As DataColumn In dt.Columns
If AddTablename = True Then
SqlStr = SqlStr & " ( " & dt.TableName & "." & col.ColumnName & " = ? ) AND "
Else
SqlStr = SqlStr & " ( " & col.ColumnName & " = ? ) AND "
End If

Dim param As New OracleParameter
param.ParameterName = "@p" & i
param.SourceColumn = col.ColumnName
If col.DataType Is System.Type.GetType("System.String") Then
param.OracleDbType = OracleDbType.Varchar2
Else
param.OracleDbType = OracleDbType.Int32
End If
param.SourceVersion = DataRowVersion.Original
cmd.Parameters.Add(param)
Next

' 最後に付加した(AND)を破棄
cmd.CommandText = cmd.CommandText & Left(SqlStr, Len(SqlStr) - 5)
cmd.Connection = cnt

CreateUpdateCommand = cmd
End Function
' ------------------------------------------------------------------------
Public Function Exec_update(ByRef SqlStr As String, ByRef NewValues As BTDBRecords2, ByVal tablename As String) As Integer
Dim dt As DataTable = GetSqlResult(SqlStr, tablename)
Dim oOleAdap As New OracleDataAdapter
Dim i As Integer

Try
' 抽出対象が存在すれば、カーソルのあるレコードを削除
If dt.Rows.Count() = 0 Then
Exec_update = 0
Else
For i = 0 To NewValues.Count - 1
If NewValues(i).Index >= dt.Columns.Count Then
Exec_update = 0
dt.Reset()
Exit Function
End If

If dt.Columns(NewValues(i).Index).DataType Is System.Type.GetType("System.String") Then
' 文字列型
dt.Rows(0).Item(NewValues(i).Index) = NewValues(i).Value
Else
' 数値型として処理
' 代入値の作成
' =
If NewValues(i).Operation = 0 Then
dt.Rows(0).Item(NewValues(i).Index) = NewValues(i).Value
' +=
ElseIf NewValues(i).Operation = 7 Then
dt.Rows(0).Item(NewValues(i).Index) = dt.Rows(0).Item(NewValues(i).Index) + CInt(NewValues(i).Value)
' -=
ElseIf NewValues(i).Operation = 9 Then
dt.Rows(0).Item(NewValues(i).Index) = dt.Rows(0).Item(NewValues(i).Index) - CInt(NewValues(i).Value)
End If
End If
Next
Try
oOleAdap.UpdateCommand = CreateUpdateCommand(dt, True)
Exec_update = oOleAdap.Update(dt)
Catch ee As Exception
oOleAdap.UpdateCommand = CreateUpdateCommand(dt, False)
Exec_update = oOleAdap.Update(dt)
End Try
End If
Catch e As Exception
Exec_update = -1
End Try
End Function
VB初心者
常連さん
会議室デビュー日: 2008/09/29
投稿数: 20
投稿日時: 2008-09-30 17:32
内容の表記に一部誤りがありました。

>oracle.data.adapterでSQLを自動生成し、テーブルを更新する
>処理を作成しております。(System.Data.OracleClientにより
              ~~~~~~~~~~~~~~~~~~~~~~~~~
                   ↑
               System.Data.Oledb の誤りです。
Jitta
ぬし
会議室デビュー日: 2002/07/05
投稿数: 6267
お住まい・勤務地: 兵庫県・海手
投稿日時: 2008-09-30 17:34
> ' UPDATEコマンドの作成

思いっきり、作成しているようなのですが?
どこが自動生成なのでしょう?
rain
ぬし
会議室デビュー日: 2006/10/19
投稿数: 549
投稿日時: 2008-09-30 17:50
コード:
Exec_update = oOleAdap.Update(dt)


のコードを実行する直前で、oOleAdap.UpdateCommand プロパティに入っている CommandオブジェクトのCommandTextやParametersの中身を確認してみるといいんじゃないでしょうか。

引用:

VB初心者さんの書き込み (2008-09-30 17:05) より:

SqlStr = SqlStr & dt.TableName & "." & col.ColumnName & " = ?, "

SqlStr = SqlStr & col.ColumnName & " = ?, "

param.ParameterName = "@p" & i


System.Data.OracleClient を使用した場合、パラメータの書式は「コロン(:) + 名前(例… :hoge )」ですね。
VB初心者
常連さん
会議室デビュー日: 2008/09/29
投稿数: 20
投稿日時: 2008-09-30 17:55
Jittaさんへ

確かに自動生成では無いですね。
申し訳ありません。

cmd.CommandTextの内容に関しては、特に使用出来ない文字は
設定されておりませんでした。

【cmd.CommandTextの内容】
"UPDATE nyukolog SET nyukolog.FIELD1 = ?, nyukolog.FIELD2 = ?, nyukolog.FIELD3 = ?, nyukolog.FIELD4 = ?, nyukolog.FIELD5 = ?, nyukolog.FIELD6 = ?, nyukolog.FIELD7 = ?, nyukolog.FIELD8 = ? WHERE ( nyukolog.FIELD1 = ? ) AND ( nyukolog.FIELD2 = ? ) AND ( nyukolog.FIELD3 = ? ) AND ( nyukolog.FIELD4 = ? ) AND ( nyukolog.FIELD5 = ? ) AND ( nyukolog.FIELD6 = ? ) AND ( nyukolog.FIELD7 = ? ) AND ( nyukolog.FIELD8 = ? )"

作成したSQL文の?に、値を代入していると思われます。
修正した部分は、System.Data.OledbオブジェクトをODP.NETオブジェクトに
変更のみです。

oOleAdap.UpdateCommand = CreateUpdateCommand(dt, True)
Exec_update = oOleAdap.Update(dt)

この時に、実行されるSQL文を確認したいと思うのですが、
どの様にすればよろしいのでしょうか?

よろしくお願いします。
masa
大ベテラン
会議室デビュー日: 2004/10/28
投稿数: 161
投稿日時: 2008-09-30 19:44
? はパラメーターを表すプレースホルダです。
私は : をつけたパラメーター名しか使ったことがないのですが、
ODP.NET では ? は使えなかったような?

@IT 「ODP.NETでOracle固有の機能を活用する 」
http://www.atmarkit.co.jp/fdb/rensai/odpdotnet01/odpdotnet04.html

OTN 「値のバインド」
http://www.oracle.com/technology/global/jp/oramag/oracle/05-sep/o55odpnet.html
masa
大ベテラン
会議室デビュー日: 2004/10/28
投稿数: 161
投稿日時: 2008-09-30 19:49
引用:


"UPDATE nyukolog SET nyukolog.FIELD1 = ?, nyukolog.FIELD2 = ?, nyukolog.FIELD3 = ?, nyukolog.FIELD4 = ?, nyukolog.FIELD5 = ?, nyukolog.FIELD6 = ?, nyukolog.FIELD7 = ?, nyukolog.FIELD8 = ? WHERE ( nyukolog.FIELD1 = ? ) AND ( nyukolog.FIELD2 = ? ) AND ( nyukolog.FIELD3 = ? ) AND ( nyukolog.FIELD4 = ? ) AND ( nyukolog.FIELD5 = ? ) AND ( nyukolog.FIELD6 = ? ) AND ( nyukolog.FIELD7 = ? ) AND ( nyukolog.FIELD8 = ? )"




エラーとは関係ありませんが、このSQLは「自動生成」されてますよね?
主キーを張ったほうがいいですよ。

主キーがないと全ての列の値が一致するかどうかがレコード一致条件になります。
where 句に各列の値が羅列されてますよね。
SQLServer の場合、こういうコマンドでトランザクションがらみの内部エラーが発生することがあります。内部でもみ消されるので厄介な現象です。
Oracle では試したことはありませんが、危険かも。

rain
ぬし
会議室デビュー日: 2006/10/19
投稿数: 549
投稿日時: 2008-09-30 21:32
引用:

VB初心者さんの書き込み (2008-09-30 17:05) より:

oracle.data.adapterでSQLを自動生成し、テーブルを更新する
処理を作成しております。(System.Data.OracleClientにより
Access MDBを更新するプログラムをOracle用に変更中)



あ、ODP.NETか。勘違いしてたorz

スキルアップ/キャリアアップ(JOB@IT)