バインド配列に変換


Mt.B  2003-09-05 01:58:40  No: 108517

質問です。というか、教えてください。

sesOra.BeginTrans
Do While Not EOF(intFno)
    Line Input #intFno, strBuf
    '1行分のデータを設定する
    strData = ""
        
    Do While InStr(strBuf, ",") > 0
        strData = strData & "'" & strQuote(Trim$(Left$(strBuf, InStr(strBuf, ",") - 1))) & "',"
        strBuf = Mid$(strBuf, InStr(strBuf, ",") + 1)
        DoEvents
    Loop
        
    strData = strData & "'" & strQuote(Trim$(strBuf)) & "'"
    lngRet = dbOra.DbExecuteSQL(strSQL & " (" & strData & ")")
    'DoEvents
Loop
sesOra.CommitTrans

↑をバインド配列を使用したものに変換したいんですけど、
うまくできません。

誰か教えてください。
よろしくお願いします。


Mt.B  2003-09-05 22:23:31  No: 108518

自己レスです。

ちなみにoo4oでやってます。

どなたかアドバイスお願いします。


魔界の仮面弁士  2003-09-07 09:06:32  No: 108519

# 回答が付かないようなので。

バインド配列のコードに関しては、ヘルプに具体例があるはずです。
oo4oのヘルプで、OraParamArrayについて調べてください。

ところで、現在の strSQL の中身はどうなっているのでしょうか?
SQLの内容によっては、バインド配列化できない事もありえますので…。


Mt.B  2003-09-08 18:55:48  No: 108520

返事ありがとうございます。

下に載せるソースはCSVファイルのインポートをするものですが、
あまりに処理が遅いためバインド配列を利用しようと考えました。

バインド配列に関しては自分なりに調べました。
配列のサンプルになると、どれもFor文になってしまうし、
EOFの場合では、どのようなソースにしてよいのかわからないので
質問させていただきました。

Public Function ImportData(ByVal vstrFilename As String) As Boolean
    Dim strSQL          As String   'SQL文
    Dim blnRet          As Boolean
    Dim lngRet          As Long
    Dim intFno          As Integer
    Dim strData         As String   '項目値
    Dim strBuf          As String   '読み込みバッファ
    Dim strErrText      As String
       
    On Error GoTo errInsertData:
    
    blnRet = False
 
    intFno = FreeFile
    Open vstrFilename For Input Access Read Lock Read Write As #intFno
    
'定義体のフィールド取得
    Line Input #intFno, strBuf
    sesOra.BeginTrans
    Do While InStr(strBuf, ",") > 0
        strSQL = strSQL & Trim$(Left$(strBuf, InStr(strBuf, ",") - 1)) & ","
        strBuf = Mid$(strBuf, InStr(strBuf, ",") + 1)
        DoEvents
    Loop
    sesOra.CommitTrans
    strSQL = "INSERT INTO ITEM (" & _
             strSQL & Trim$(strBuf) & _
             ") VALUES"
        
'テーブルにデータをINSERTする
    sesOra.BeginTrans
    Do While Not EOF(intFno)
        Line Input #intFno, strBuf
    '1行分のデータを設定する
        strData = ""
        
        Do While InStr(strBuf, ",") > 0
            strData = strData & "'" & strQuote(Trim$(Left$(strBuf, InStr(strBuf, ",") - 1))) & "',"
            strBuf = Mid$(strBuf, InStr(strBuf, ",") + 1)
            DoEvents
        Loop
        
        strData = strData & "'" & strQuote(Trim$(strBuf)) & "'"
        lngRet = dbOra.DbExecuteSQL(strSQL & " (" & strData & ")")
        'DoEvents
    Loop
    sesOra.CommitTrans
    blnRet = True
    
exitInsertData:
    On Error Resume Next
    Close #intFno
'    lblInsert.Caption = "設定完了"
    ImportData = blnRet
    Exit Function

errInsertData:
    If sesOra.LastServerErr = 0 Then
        If dbOra.LastServerErr = 0 Then
            strErrText = Error$
        Else
            strErrText = dbOra.LastServerErrText
            dbOra.LastServerErrReset
        End If
    Else
        strErrText = sesOra.LastServerErrText
        sesOra.LastServerErrReset
    End If
    MsgBox strErrText, vbOKOnly + vbExclamation, "Error"
    Resume exitInsertData:
    Resume Next
    
End Function

Private Function strQuote(ByVal vstrItem As String) As String
    Dim strWork         As String

    strWork = ""
    Do While InStr(vstrItem, "'") > 0
        strWork = strWork & Left$(vstrItem, InStr(vstrItem, "'") - 1) & "''"
        vstrItem = Mid$(vstrItem, InStr(vstrItem, "'") + 1)
        DoEvents
    Loop
    strQuote = strWork & vstrItem
End Function

このような場合のSQLでは配列化は可能でしょうか?

よろしくお願いします。


魔界の仮面弁士  2003-09-08 19:50:21  No: 108521

あら。知りたかったのは、「strSQL の中身」だけだったのですが……
現状のstrSQL の生成手順を示してくださったようですね。m(_ _)m

vstrFilename の内容がわからなかったので、最終的なstrSQLの中身が
どうなるのかわかりませんでしたが、おおよその類推はできました。現状は、
  strSQL = "INSERT INTO ITEM (" & 列定義 & ") VALUES (" & 値定義 & ")"
のようなSQLを動的に作成し、それを ExecuteSQL している…という事ですよね。

> 配列のサンプルになると、どれもFor文になってしまうし、
For文でもDo文でも、ループである事には変わりありませんよね?

まず、バインド配列変数を定義するために、AddTableメソッドに
  バインド変数名(例: "STAFF_NAME")
  入出力方向(例: ORAPARM_INPUT)
  データ型(例: ORATYPE_CHAR)
  配列の行数
  データ型のサイズ(数値または文字列の時のみ指定)
という5個(4個)のパラメータを指定して、各パラメータを定義します。

なお、配列の行数に関しては、元データの総件数を指定すればOKです。
# 元データの行数が多すぎぎる場合は、指定する件数を減らして、
# 何回かに分けて実行した方が良いかもしれません。適宜調整してください。

次に、put_Valueメソッドで、バインド配列に値を格納して行きます。

最後に、CreateSqlメソッドで
  strSQL = "INSERT INTO STAFF_NAME (ID, STAFF_NAME, MAIL) VALUES (:ID, :STAFF_NAME, :MAIL)"
といった形式の SQL を実行してやればOKです。
(上記のSQLの場合、"ID", "STAFF_NAME", "MAIL" という3種のバインド変数が使われます)


Mt.B  2003-09-08 22:32:40  No: 108522

レスありがとうございます。

>なお、配列の行数に関しては、元データの総件数を指定すればOKです。

とありますが、
データ件数がわからないのでEOFを使っています。
総件数を指定すればOKとありますが、総件数を調べるSQL文を発行して、
その値を指定すれば良いということでしょうか?

># 元データの行数が多すぎぎる場合は、指定する件数を減らして、
># 何回かに分けて実行した方が良いかもしれません。適宜調整してください。

ちなみに開発本番では3桁のデータ件数の予定ですが、
現状5桁のデータ件数で開発を進めています。
EOFで最終行をとっているとき、回数をわけて実行するには
どうのような方法でループを実行したらよいのでしょうか?

簡単な質問ばかりですみません。
よろしくお願いします。


Mt.B  2003-09-08 23:04:42  No: 108523

自己レスです。
ちょっと勘違いして送ってしまいました。

>なお、配列の行数に関しては、元データの総件数を指定すればOKです。
とありますが、
データ件数がわからないのでEOFを使っています。
総件数を指定すればOKとありますが、総件数を調べるSQL文を発行して、
その値を指定すれば良いということでしょうか?

># 元データの行数が多すぎぎる場合は、指定する件数を減らして、
># 何回かに分けて実行した方が良いかもしれません。適宜調整してください。

ちなみに開発本番では3桁のデータ件数の予定ですが、
現状5桁のデータ件数で開発を進めています。
この場合、パラメータの配列数はとりあえず
100件ということでいいのでしょうか?

あと、EOFのときのループで回数をわけるときは
どのようなコーディングになるんでしょうか?

よろしくお願いします。


魔界の仮面弁士  2003-09-09 00:11:46  No: 108524

提示されたコードを見た限りは、元データはCSVファイルなのですよね?

であれば、ファイル終端に到達するまでに、Line Input #の実行回数を
数えば、総件数もわかりますよね。

> この場合、パラメータの配列数はとりあえず
> 100件ということでいいのでしょうか?
適切な配列数というのはケースバイケースです。
ネットワークの都合やユーザー数、DBの設定などに応じて、
適切な件数は変わります。実際に試して確認してください。

とりあえずは全て一括で送ってみて、それで問題があるようなら、
件数を減らしていくという方向で考えてみては如何でしょう。


Mt.B  2003-09-09 02:44:40  No: 108525

返事遅くなりました。

テーブルの項目が9個あるんですけど、こんな感じ↓でいいんでしょうか?
とりあえずデータが1万件と仮定しています。

'バインド配列変数の作成
Dim Item_code_Array     As OraParamArray
Dim Item_name_Array     As OraParamArray
Dim Youryou_Array       As OraParamArray
Dim Kana_name_Array     As OraParamArray
Dim Sekitukesuu_Array   As OraParamArray
Dim Irisuu_Array        As OraParamArray
Dim Size_w_Array        As OraParamArray
Dim Size_d_Array        As OraParamArray
Dim Size_h_Array        As OraParamArray

OraDatabase.Parameters.AddTable "Item_code_Array", ORAPARM_INPUT, ORATYPE_NUMBER, 10000, 14
OraDatabase.Parameters.AddTable "Item_name_Array", ORAPARM_INPUT, ORATYPE_VARCHR2, 10000, 40
OraDatabase.Parameters.AddTable "Youryou_Array", ORAPARM_INPUT, ORATYPE_VARCHAR2, 10000, 30
OraDatabase.Parameters.AddTable "kana_name_Array", ORAPARM_INPUT, ORATYPE_VARCHAR2, 10000, 40
OraDatabase.Parameters.AddTable "Sekitukesuu_Array", ORAPARM_INPUT, ORATYPE_NUMBER, 10000,9
OraDatabase.Parameters.AddTable "Irisuu_Array", ORAPARM_INPUT, ORATYPE_NUMBER, 10000, 4
OraDatabase.Parameters.AddTable "Size_w_Array", ORAPARM_INPUT, ORATYPE_NUMBER, 10000, 4
OraDatabase.Parameters.AddTable "Size_d_Array", ORAPARM_INPUT, ORATYPE_NUMBER, 10000, 4
OraDatabase.Parameters.AddTable "Size_h_Array", ORAPARM_INPUT, ORATYPE_NUMBER, 10000, 4

Set Item_code_Array = oraDb.Parameters("Item_code_Array")
Set Item_name_Array = oraDb.Parameters("Item_name_Array")
Set Youryou_Array = oraDb.Parameters("Youryou_Array")
Set Kana_name_Array = oraDb.Parameters("Kana_name_Array")
Set Sekitukesuu_Array = oraDb.Parameters("Sekitukesuu_Array")
Set Irisuu_Array = oraDb.Parameters("Irisuu_Array")
Set Size_w_Array = oraDb.Parameters("Size_w_Array")
Set Size_d_Array = oraDb.Parameters("Size_d_Array")
Set Size_h_Array = oraDb.Parameters("Size_h_Array")

よろしくお願いします。


※返信する前に利用規約をご確認ください。

※Google reCAPTCHA認証からCloudflare Turnstile認証へ変更しました。






  このエントリーをはてなブックマークに追加