Esta situación no es infrecuente cuando se trata de INSERCIONES masivas en tablas vinculadas ODBC en Access. En el caso de la siguiente consulta de acceso
INSERT INTO METER_DATA (MPO_REFERENCE)
SELECT MPO_REFERENCE FROM tblTempSmartSSP
donde [METER_DATA] es una tabla vinculada de ODBC y [tblTempSmartSSP] es una tabla de acceso local (nativa), ODBC está algo limitado en lo inteligente que puede ser porque tiene que ser capaz de adaptarse a una amplia gama de bases de datos de destino cuyas capacidades pueden variar. muy. Desafortunadamente, a menudo significa que, a pesar de la única instrucción SQL de Access, lo que realmente se envía a la base de datos remota (vinculada) es un INSERT (o equivalente) separado para cada fila en la tabla local . Comprensiblemente, eso puede resultar muy lento si la tabla local contiene una gran cantidad de filas.
Opción 1:inserciones masivas nativas en la base de datos remota
Todas las bases de datos tienen uno o más mecanismos nativos para la carga masiva de datos:Microsoft SQL Server tiene "bcp" y BULK INSERT
y Oracle tiene "SQL*Loader". Estos mecanismos están optimizados para operaciones a granel y, por lo general, ofrecerán importantes ventajas de velocidad. De hecho, si es necesario importar los datos a Access y "masajearlos" antes de transferirlos a la base de datos remota, aún puede ser más rápido volcar los datos modificados en un archivo de texto y luego importarlos en masa a la base de datos remota.
Opción 2:usar una consulta de transferencia en Access
Si los mecanismos de importación masiva no son una opción factible, otra posibilidad es crear una o más consultas de transferencia en Access para cargar los datos mediante instrucciones INSERT que pueden insertar más de una fila a la vez.
Por ejemplo, si la base de datos remota fuera SQL Server (2008 o posterior), podríamos ejecutar una consulta de paso a través de Access (T-SQL) como esta
INSERT INTO METER_DATA (MPO_REFERENCE) VALUES (1), (2), (3)
para insertar tres filas con una instrucción INSERT.
Según una respuesta a otra pregunta anterior aquí, la sintaxis correspondiente para Oracle sería
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;
Probé este enfoque con SQL Server (ya que no tengo acceso a una base de datos de Oracle) usando una tabla nativa [tblTempSmartSSP] con 10 000 filas. El código...
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
... tardó aproximadamente 100 segundos en ejecutarse en mi entorno de prueba.
Por el contrario, el siguiente código, que crea INSERTOS de varias filas como se describe anteriormente (usando lo que Microsoft llama un Constructor de valor de tabla) ...
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
... tomó entre 1 y 2 segundos para producir los mismos resultados.
(Los constructores de valores de tabla T-SQL se limitan a insertar 1000 filas a la vez, por lo que el código anterior es un poco más complicado de lo que sería de otra manera).