Pregunta

Quiero comparar dos archivos ms-access .mdb para verificar que los datos que contienen son los mismos en ambos.

¿Cómo puedo hacer esto?

¿Fue útil?

Solución

He hecho este tipo de cosas en el 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 estaba dirigido por un MDB, en otros, era una base de datos MySQL. Para el MDB, lo acabamos de descargar, para MySQL, ejecutamos scripts en el sitio web para exportar y enviar 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 fue 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 a MDB B la que está descargando para comparar. Lo que tienes que verificar 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 se adjuntarán de MDB B a MDB A.

  3. registros que existen en ambos, que deberán compararse campo por campo.

Los pasos # 1 y # 2 se realizan con bastante facilidad con consultas que usan una combinación externa para encontrar los registros faltantes. 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 es idéntica. Por lo tanto, utiliza 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. Así que probablemente querrá un CASO SELECCIONADO 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.

El código de mi ejemplo no usa realmente la estructura anterior para definir la cláusula WHERE porque se limita a los campos que funcionan muy bien en comparación concatenados con un ZLS (campos de texto). Lo que está debajo es bastante complicado de leer, pero es básicamente una expansión en 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 el asunto de manera diferente. Pero eso se complica bastante dependiendo de la salida,

Si todo lo que quiere saber es si dos MDB son idénticos, primero debe verificar el número de registros en cada tabla, y si tiene una no coincidencia, abandona y le dice al usuario que los MDB no están lo mismo. Si las cuentas de registro son iguales, entonces debe verificar campo por campo, lo que creo que se logra mejor con el SQL columna por columna escrito dinámicamente, tan pronto como uno de los SELECTOS de SQL resultantes devuelve 1 o más registros, usted abortará y dígale a su usuario que los MDB no son idénticos.

La parte complicada es si quieres registrar las diferencias e informar al usuario, pero si entiendes eso, esta publicación ya interminable será 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 declaración SELECT que se limita a los campos que desea comparar, mientras que strTmpDB es la ruta / nombre de archivo de los otros MDB (MDB B en nuestro ejemplo). El código supone que strTmpDB tiene qdfNewMembers y qdfOldMembers ya creados (el código original escribe el QueryDef guardado sobre la marcha). Podría ser igual de fácil que sean 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 se escribió).

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.

Otros consejos

Puede probar AccessDiff (producto pagado). 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 tablas de bases de datos y simplemente compare los archivos de texto volcados utilizando BeyondCompare (o cualquier otra herramienta de comparación de texto). ¡Crudo pero puede funcionar!

Tengo muy buena experiencia con Comparador de bases de datos cruzadas . Es capaz de comparar estructura y / o datos.

Consulte la sección de bases de datos Compare Access en Utilidades, productos y herramientas de terceros de Microsoft Access , módulos, etc. en mi sitio web.

He agregado " tabla diff " función para mi accdbmerge no hace mucho tiempo. Creo que esta respuesta no ayudará a resolver la pregunta original, pero puede ser útil para alguien que tenga el mismo problema en el futuro.

Si desea saber si los archivos son idénticos, entonces

fc file1.mdb file2.mdb 

en una línea de comando de DOS.

Si los archivos no son idénticos pero sospecha que contienen las mismas tablas y registros, entonces la forma más fácil sería escribir rápidamente una pequeña utilidad que abra las bases de datos y los ciclos a través de las tablas de ambos realizando una consulta heterogénea para extraer el Diff entre los dos archivos.

Hay algunas herramientas por ahí que harán esto por ti, pero todas parecen ser shareware.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top