• ベストアンサー

SQLの重複検索の高速化について

EXCELのデータをSQLサーバにインポートさせているのですが、 インポートの重複有無を判断するために3つのキーを 使用しています。 現状の方法としては、  Dim rsRecord As ADODB.Recordset  Set rsRecord = New ADODB.Recordset  rsRecord.Open XXXX 'レコードを開く  rsRecord.Filter = "(A='あ') And (B='い') And (C='う')" のような形でrsRecordが1以上かどうかで重複を確認しています。 (Filterのキーとなる”あ、い、う”はEXCELから取得するデータです。) 上記で重複はチェックが出来るのですが、DBの都合上、1レコード辺り 16回繰り返す必要がある為、1レコードの処理に2秒程度かかっています。 EXCELのデータ数が多いため、1回のインポート処理に30分以上掛かってしまっており、困っています。 重複チェックを高速にする良い方法はないでしょうか。 データベース初心者のため、色々方法を探した結果、上のような 処理以外見当たらず困っています。よろしくお願いします。

質問者が選んだベストアンサー

  • ベストアンサー
noname#140971
noname#140971
回答No.1

IF Nnot DBLookup(列名,テーブル名, 条件, False) Then   インポート手続き End If 次のDBLookup関数は、pubCNNSTRINGをSQL Sereverのそれにすれば動作します。 フィルターをかけるよりは速いとは思います。 ただ、接続と切断を繰り返すのが難点。 ただ、AccessのDLookup関数とくらべたら150倍速で動作するのは間違いありません。 ですから<1レコードの処理に2秒>という遅さではないのは確実だと思います。 Public Const pubCNNSTRING="XXXXXXXXXX" Public Function DBLookup(ByVal strField As String, _              ByVal strTable As String, _              Optional ByVal strWhere As String = "", _              Optional ByVal ReturnValue = Null) As Variant On Error GoTo Err_DBLookup    Dim DataValue    Dim strQuerySQL As String    Dim rst     As ADODB.Recordset    Set rst = New ADODB.Recordset    strQuerySQL = "SELECT " & strField & " FROM " & strTable    If Len(strWhere) > 0 Then      strQuerySQL = strQuerySQL & " WHERE " & strWhere    End If    With rst      .Open strQuerySQL, _         pubCNNSTRING, _         adOpenStatic, _         adLockReadOnly      If Not .BOF Then        .MoveFirst        DataValue = .Fields(0)      End If    End With Exit_DBLookup: On Error Resume Next    rst.Close    Set rst = Nothing    DBLookup = IIf(Len(DataValue & "") = 0, ReturnValue, DataValue)    Exit Function Err_DBLookup:    MsgBox "SELECT 文の実行時にエラーが発生しました。(DBLookup)" & Chr$(13) & Chr$(13) & _       "・Err.Description=" & Err.Description & Chr$(13) & _       "・SQL Text=" & strQuerySQL, _       vbExclamation, " 関数エラーメッセージ"    Resume Exit_DBLookup End Function ※SQL文を直接渡せば、もうチビットは高速化します。 ※DBCount()を使う手もありますが、どっちが速いか不明。 ※「一時的にWHERE節に関連する列にインデックス」は試す価値がとも。 http://www.accessclub.jp/ado/18.html SEEKメソッドはDAOでしか使ったことがありません。 しかし、DBLookup()のSEEK版なら、もっと速いかもです。

Boo2
質問者

お礼

追伸ですいません。 色々試した結果、出来ました。 1レコードで1秒未満で実行できました。 ありがとうございます!!

Boo2
質問者

補足

早々なご回答ありがとうございました。 説明が不足していたのですが、インポートするEXCELの1列の情報の中で、16個のDBのレコードが出来る為、DBLookUpでそういった処理は出来ますでしょうか。 イメージとしてはこんな感じの事をしています。 [EXCEL] Index,Title,Ver1,Ver2,…,Ver16 [DB] Index,Title,Ver DBのVerが、Excelの一列にあるVer1~16のデータが別レコードとして、存在しており、この3つでEXCELデータがDB内に存在するのかを確認しています。 この場合DBLookUpへの入力は、WHERE句に、Index,Title,Verの比較条件をいれ、Verの条件を1~16で指定することになるのでしょうか。 DB初心者で申し訳ありませんが、よろしくお願いします。

その他の回答 (1)

  • jamshid6
  • ベストアンサー率88% (591/669)
回答No.2

件数次第ですが、1000~2000件までならば、Excelのデータを読み込んで、 "SELECT tmp.* FROM   (SELECT '値' A,'値' B, '値' C UNION ALL SELECT '値','値', '値' UNION ALL ...) tmp INNER JOIN (SQL Serverのテーブル) t ON t.A=tmp.A AND t.B=tmp.B AND t.C=tmp.C" という文字列を組み上げて実行するという手もあります。 これだと1クエリで全件チェックされ、返って来たものが重複しています。 (長い文字列なので、Mid$などを使って組み上げます) 組み上げた中のtmpに当たる部分は、頭に"INSERT INTO (SQL Serverのテーブル)" と付ければ、INSERTも1クエリでできます。 数千件以上あるなら、一旦ExcelのデータをSQL Server側のワークテーブルに入れた方がいいと思います。 入れてしまえば、重複チェック/チェック後のINSERTは1クエリでできます。

Boo2
質問者

お礼

回答ありがとうございます。 ただ、SQLに関して、知識が浅いため、一つ一つのキーワードは わかっても今ひとつ理解できず、回答を活かせませんでした。。。 もう少し、SQLを勉強します。

関連するQ&A