Saltar al contenido

¿Puedo comparar dos archivos ms-access?

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:

  1. 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).

  2. registros que existen en MDB B pero no en MDB A. Estos los agregará de MDB B a MDB A.

  3. 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!

¡Haz clic para puntuar esta entrada!
(Votos: 0 Promedio: 0)



Utiliza Nuestro Buscador

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *