- ベストアンサー
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分以上掛かってしまっており、困っています。 重複チェックを高速にする良い方法はないでしょうか。 データベース初心者のため、色々方法を探した結果、上のような 処理以外見当たらず困っています。よろしくお願いします。
- みんなの回答 (2)
- 専門家の回答
質問者が選んだベストアンサー
- ベストアンサー
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版なら、もっと速いかもです。
その他の回答 (1)
- jamshid6
- ベストアンサー率88% (591/669)
件数次第ですが、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クエリでできます。
お礼
回答ありがとうございます。 ただ、SQLに関して、知識が浅いため、一つ一つのキーワードは わかっても今ひとつ理解できず、回答を活かせませんでした。。。 もう少し、SQLを勉強します。
お礼
追伸ですいません。 色々試した結果、出来ました。 1レコードで1秒未満で実行できました。 ありがとうございます!!
補足
早々なご回答ありがとうございました。 説明が不足していたのですが、インポートする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初心者で申し訳ありませんが、よろしくお願いします。