Situasi ini tidak jarang terjadi ketika berhadapan dengan INSERT massal ke tabel tertaut ODBC di Access. Dalam kasus kueri Access berikut
INSERT INTO METER_DATA (MPO_REFERENCE)
SELECT MPO_REFERENCE FROM tblTempSmartSSP
di mana [METER_DATA] adalah tabel tertaut ODBC dan [tblTempSmartSSP] adalah tabel Access lokal (asli), ODBC agak terbatas dalam seberapa pintarnya karena harus mampu mengakomodasi berbagai basis data target yang kemampuannya dapat bervariasi sangat. Sayangnya, ini sering berarti bahwa meskipun pernyataan Access SQL tunggal, apa yang sebenarnya dikirim ke database jarak jauh (tertaut) adalah INSERT (atau setara) terpisah untuk setiap baris dalam tabel lokal . Dapat dimengerti, itu bisa menjadi sangat lambat jika tabel lokal berisi banyak baris.
Opsi 1:Sisipan massal asli ke database jarak jauh
Semua database memiliki satu atau lebih mekanisme asli untuk memuat data secara massal:Microsoft SQL Server memiliki "bcp" dan BULK INSERT
, dan Oracle memiliki "SQL*Loader". Mekanisme ini dioptimalkan untuk operasi massal dan biasanya akan menawarkan keuntungan kecepatan yang signifikan. Bahkan, jika data perlu diimpor ke Access dan "dipijat" sebelum ditransfer ke database jarak jauh, masih bisa lebih cepat untuk membuang data yang dimodifikasi kembali ke file teks dan kemudian mengimpornya secara massal ke database jarak jauh.
Opsi 2:Menggunakan kueri terusan di Access
Jika mekanisme impor massal bukanlah opsi yang layak, maka kemungkinan lain adalah membuat satu atau beberapa kueri terusan di Access untuk mengunggah data menggunakan pernyataan INSERT yang dapat menyisipkan lebih dari satu baris sekaligus.
Misalnya, jika database jarak jauh adalah SQL Server (2008 atau yang lebih baru) maka kita dapat menjalankan kueri Access pass-through (T-SQL) seperti ini
INSERT INTO METER_DATA (MPO_REFERENCE) VALUES (1), (2), (3)
untuk menyisipkan tiga baris dengan satu pernyataan INSERT.
Menurut jawaban untuk pertanyaan lain sebelumnya di sini sintaks yang sesuai untuk Oracle adalah
INSERT ALL
INTO METER_DATA (MPO_REFERENCE) VALUES (1)
INTO METER_DATA (MPO_REFERENCE) VALUES (2)
INTO METER_DATA (MPO_REFERENCE) VALUES (3)
SELECT * FROM DUAL;
Saya menguji pendekatan ini dengan SQL Server (karena saya tidak memiliki akses ke database Oracle) menggunakan tabel [tblTempSmartSSP] asli dengan 10.000 baris. Kode ...
Sub LinkedTableTest()
Dim cdb As DAO.Database
Dim t0 As Single
t0 = Timer
Set cdb = CurrentDb
cdb.Execute _
"INSERT INTO METER_DATA (MPO_REFERENCE) " & _
"SELECT MPO_REFERENCE FROM tblTempSmartSSP", _
dbFailOnError
Set cdb = Nothing
Debug.Print "Elapsed time " & Format(Timer - t0, "0.0") & " seconds."
End Sub
... membutuhkan waktu sekitar 100 detik untuk dieksekusi di lingkungan pengujian saya.
Sebaliknya kode berikut, yang membangun INSERT multi-baris seperti yang dijelaskan di atas (menggunakan apa yang disebut Microsoft sebagai Konstruktor Nilai Tabel) ...
Sub PtqTest()
Dim cdb As DAO.Database, rst As DAO.Recordset
Dim t0 As Single, i As Long, valueList As String, separator As String
t0 = Timer
Set cdb = CurrentDb
Set rst = cdb.OpenRecordset("SELECT MPO_REFERENCE FROM tblTempSmartSSP", dbOpenSnapshot)
i = 0
valueList = ""
separator = ""
Do Until rst.EOF
i = i + 1
valueList = valueList & separator & "(" & rst!MPO_REFERENCE & ")"
If i = 1 Then
separator = ","
End If
If i = 1000 Then
SendInsert valueList
i = 0
valueList = ""
separator = ""
End If
rst.MoveNext
Loop
If i > 0 Then
SendInsert valueList
End If
rst.Close
Set rst = Nothing
Set cdb = Nothing
Debug.Print "Elapsed time " & Format(Timer - t0, "0.0") & " seconds."
End Sub
Sub SendInsert(valueList As String)
Dim cdb As DAO.Database, qdf As DAO.QueryDef
Set cdb = CurrentDb
Set qdf = cdb.CreateQueryDef("")
qdf.Connect = cdb.TableDefs("METER_DATA").Connect
qdf.ReturnsRecords = False
qdf.sql = "INSERT INTO METER_DATA (MPO_REFERENCE) VALUES " & valueList
qdf.Execute dbFailOnError
Set qdf = Nothing
Set cdb = Nothing
End Sub
... membutuhkan waktu antara 1 dan 2 detik untuk menghasilkan hasil yang sama.
(Konstruktor Nilai Tabel T-SQL dibatasi untuk menyisipkan 1000 baris sekaligus, jadi kode di atas sedikit lebih rumit daripada yang seharusnya.)