Тази ситуация не е необичайна, когато се работи с групови INSERT към ODBC свързани таблици в Access. В случай на следната заявка за достъп
INSERT INTO METER_DATA (MPO_REFERENCE)
SELECT MPO_REFERENCE FROM tblTempSmartSSP
където [METER_DATA] е ODBC свързана таблица и [tblTempSmartSSP] е локална (родна) таблица за достъп, ODBC е донякъде ограничена в това колко интелигентна може да бъде, тъй като трябва да може да побере широк спектър от целеви бази данни, чиито възможности могат да варират значително. За съжаление, това често означава, че въпреки единичния SQL оператор на Access, това, което всъщност се изпраща към отдалечената (свързана) база данни, е отделен INSERT (или еквивалент) за всеки ред в локалната таблица . Разбираемо е, че това може да се окаже много бавно, ако локалната таблица съдържа голям брой редове.
Опция 1:Групови вмъквания в собствена база към отдалечената база данни
Всички бази данни имат един или повече естествени механизми за групово зареждане на данни:Microsoft SQL Server има "bcp" и BULK INSERT
, а Oracle има "SQL*Loader". Тези механизми са оптимизирани за групови операции и обикновено предлагат значителни предимства в скоростта. Всъщност, ако данните трябва да бъдат импортирани в Access и „масажирани“ преди да бъдат прехвърлени към отдалечената база данни, все пак може да бъде по-бързо да изхвърлите модифицираните данни обратно в текстов файл и след това групово да ги импортирате в отдалечената база данни.
Опция 2:Използване на преходна заявка в Access
Ако механизмите за групово импортиране не са осъществима опция, тогава друга възможност е да се изградят една или повече преминаващи заявки в Access за качване на данните с помощта на оператори INSERT, които могат да вмъкват повече от един ред наведнъж.
Например, ако отдалечената база данни беше SQL Server (2008 или по-нова версия), тогава бихме могли да изпълним заявка за достъп (T-SQL) като тази
INSERT INTO METER_DATA (MPO_REFERENCE) VALUES (1), (2), (3)
за да вмъкнете три реда с един израз INSERT.
Според отговор на друг по-ранен въпрос тук съответният синтаксис за Oracle би бил
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;
Тествах този подход със SQL Server (тъй като нямам достъп до база данни на Oracle), използвайки собствена таблица [tblTempSmartSSP] с 10 000 реда. Кодът ...
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
... отне приблизително 100 секунди за изпълнение в моята тестова среда.
За разлика от следния код, който изгражда многоредови INSERT, както е описано по-горе (използвайки това, което Microsoft нарича конструктор на стойност на таблица) ...
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
... отне между 1 и 2 секунди, за да се получат същите резултати.
(Конструкторите на стойности на таблица в T-SQL са ограничени до вмъкване на 1000 реда наведнъж, така че горният код е малко по-сложен, отколкото би бил иначе.)