Solución:
He hecho este tipo de cosas en código muchas, muchas veces, principalmente en los casos en que un MDB local necesitaba que se le aplicaran actualizaciones extraídas de los datos ingresados en un sitio web. En un caso, el sitio web fue impulsado por un MDB, en otros, fue una base de datos MySQL. Para el MDB, lo acabamos de descargar, para MySQL, ejecutamos scripts en el sitio web para exportar y archivos de texto FTP.
Ahora, el punto principal es que queríamos comparar los datos en el MDB local con los datos descargados del sitio web y actualizar el MDB local para reflejar los cambios realizados en el sitio web (no, no era posible utilizar una sola fuente de datos – – fue lo primero que sugerí, pero no fue factible).
Llamemos a MDB A su base de datos local y MDB B a la que está descargando para comparar. Lo que tienes que comprobar es:
-
registros que existen en MDB A pero no en MDB B. Estos pueden o no ser candidatos para su eliminación (esto dependerá de sus datos particulares).
-
registros que existen en MDB B pero no en MDB A. Estos los agregará de MDB B a MDB A.
-
registros que existen en ambos, que deberán compararse campo por campo.
Los pasos n. ° 1 y n. ° 2 se realizan con bastante facilidad con consultas que utilizan una combinación externa para encontrar los registros que faltan. El paso 3 requiere algo de código.
El principio detrás del código es que la estructura de todas las tablas en ambos MDB son idénticas. Entonces, usa DAO para recorrer la colección TableDefs, abrir un conjunto de registros y recorrer la colección de campos para ejecutar una declaración SQL en cada columna de cada tabla que actualiza los datos o genera una lista de las diferencias.
La estructura básica detrás del código es:
Set rs = db.OpenRecordset("[SQL statement with the fields you want compared]")
For Each fld In rs.Fields
' Write a SQL string to update all the records in this column
' where the data doesn't match
strSQL = "[constructed SQL here]"
db.Execute strSQL, dbFailOnError
Next fld
Ahora, la mayor complejidad aquí es que su cláusula WHERE para cada campo debe ser diferente: los campos de texto deben tratarse de manera diferente a los campos numéricos y de datos. Por lo tanto, probablemente querrá un SELECT CASE que escriba su cláusula WHERE según el tipo de campo:
Select Case fld.Type
Case dbText, dbMemo
Case Else
End Select
Querrá usar Nz () para comparar los campos de texto, pero usaría Nz (TextField, ”) para eso, mientras usa Nz (NumericField, 0) para campos numéricos o campos de fecha.
Mi código de ejemplo en realidad no usa la estructura anterior para definir la cláusula WHERE porque está limitado a campos que funcionan muy bien comparando concatenados con un ZLS (campos de texto). Lo que se muestra a continuación es bastante complicado de leer, pero básicamente es una expansión de la estructura anterior.
Fue escrito para la eficiencia de las actualizaciones, ya que ejecuta una ACTUALIZACIÓN SQL para cada campo de la tabla, que es mucho más eficiente que ejecutar una ACTUALIZACIÓN SQL para cada fila. Si, por otro lado, no desea hacer una actualización, pero desea una lista de las diferencias, puede tratar todo de manera diferente. Pero eso se vuelve bastante complicado según el resultado,
Si todo lo que desea saber es si dos MDB son idénticos, primero debe verificar el número de registros en cada tabla, y si tiene uno que no coincide, salga y le diga al usuario que los MDB no son los mismos. Si los recuentos de registros son los mismos, entonces debe verificar campo por campo, lo que creo que se logra mejor con SQL columna por columna escrito dinámicamente; tan pronto como uno de los SELECTS de SQL resultantes devuelva 1 o más registros, aborta y dígale a su usuario que los MDB no son idénticos.
La parte complicada es si desea registrar las diferencias e informar al usuario, ¡pero entrar en eso haría que esta publicación ya interminable sea aún más larga!
Lo que sigue es solo una parte del código de una subrutina más grande que actualiza la consulta guardada qdfOldMembers (de MDB A) con datos de qdfNewMembers (de MDB B). El primer argumento, strSQL, es una instrucción SELECT que se limita a los campos que desea comparar, mientras que strTmpDB es la ruta / nombre de archivo del otro MDB (MDB B en nuestro ejemplo). El código asume que strTmpDB tiene qdfNewMembers y qdfOldMembers ya creados (el código original escribe el QueryDef guardado sobre la marcha). También podrían ser nombres de tabla directos (la única razón por la que uso una consulta guardada es porque los nombres de campo no coinciden exactamente entre los dos MDB para los que fue escrito).
Public Sub ImportMembers(strSQL As String, strTmpDB As String)
Const STR_QUOTE = """"
Dim db As Database
Dim rsSource As Recordset '
Dim fld As Field
Dim strUpdateField As String
Dim strZLS As String
Dim strSet As String
Dim strWhere As String
' EXTENSIVE CODE LEFT OUT HERE
Set db = Application.DBEngine(0).OpenDatabase(strTmpDB)
' UPDATE EXISTING RECORDS
Set rsSource = db.OpenRecordset(strSQL)
strSQL = "UPDATE qdfNewMembers INNER JOIN qdfOldMembers ON "
strSQL = strSQL & "qdfNewMembers.EntityID = qdfOldMembers.EntityID IN '" _
& strTmpDB & "'"
If rsSource.RecordCount <> 0 Then
For Each fld In rsSource.Fields
strUpdateField = fld.Name
'Debug.Print strUpdateField
If InStr(strUpdateField, "ID") = 0 Then
If fld.Type = dbText Then
strZLS = " & ''"
Else
strZLS = vbNullString
End If
strSet = " SET qdfOldMembers." & strUpdateField _
& " = varZLStoNull(qdfNewMembers." & strUpdateField & ")"
strWhere = " WHERE " & "qdfOldMembers." & strUpdateField & strZLS _
& "<>" & "qdfNewMembers." & strUpdateField & strZLS _
& " OR (IsNull(qdfOldMembers." & strUpdateField _
& ")<>IsNull(varZLStoNull(qdfNewMembers." _
& strUpdateField & ")));"
db.Execute strSQL & strSet & strWhere, dbFailOnError
'Debug.Print strSQL & strSet & strWhere
End If
Next fld
End If
End Sub
Código para la función varZLSToNull ():
Public Function varZLStoNull(varInput As Variant) As Variant
If Len(varInput) = 0 Then
varZLStoNull = Null
Else
varZLStoNull = varInput
End If
End Function
No sé si eso es demasiado complejo para tener sentido, pero tal vez ayude a alguien.
Puede probar AccessDiff (producto de pago). Tiene la capacidad de comparar el esquema, los datos y también acceder a los objetos. Tiene una GUI y también una interfaz de línea de comandos.
Divulgación: soy el creador de esta herramienta.
Tome volcados de texto de las tablas de la base de datos y simplemente compare los archivos de texto volcados usando BeyondCompare (o cualquier otra herramienta de comparación de texto). ¡Crudo pero puede funcionar!