Question

Je souhaite comparer deux fichiers .mdb ms-access pour vérifier que les données qu'ils contiennent sont identiques dans les deux.

Comment puis-je faire cela?

Était-ce utile?

La solution

J'ai souvent fait ce genre de chose dans le code, surtout dans les cas où une BMD locale devait appliquer des mises à jour à partir de données entrées sur un site Web. Dans un cas, le site Web était géré par un MDB, dans d'autres, il s'agissait d'une base de données MySQL. Pour la MDB, nous venons de le télécharger, pour MySQL, nous avons exécuté des scripts sur le site Web pour exporter et les fichiers texte FTP.

Maintenant, l’essentiel est que nous voulions comparer les données de la BMD locale avec celles téléchargées sur le site Web et mettre à jour la MDB locale afin de refléter les modifications apportées sur le site Web (non, il n’était pas possible d’utiliser un seul logiciel). source de données - c’était la première chose que j’avais suggérée, mais ce n’était pas faisable).

Appelons MDB A votre base de données locale et MDB B celle que vous téléchargez pour comparaison. Ce que vous devez vérifier, c'est:

  1. enregistrements existant dans la MDB A mais pas dans la MDB B. Ils peuvent ou non être supprimés (cela dépend de vos données).

  2. enregistrements existant dans la MDB B mais pas dans la MDB A. Vous les ajouterez de la MDB B à la MDB A.

  3. enregistrements existant dans les deux cas, qui devront être comparés champ par champ.

Les étapes n ° 1 et n ° 2 sont assez faciles à réaliser avec des requêtes qui utilisent une jointure externe pour rechercher les enregistrements manquants. L'étape 3 nécessite du code.

Le code repose sur le principe que la structure de toutes les tables des deux bases de données système est identique. Ainsi, vous utilisez DAO pour parcourir la collection TableDefs, ouvrir un jeu d'enregistrements et pour parcourir la collection de champs afin d'exécuter une instruction SQL sur chaque colonne de chaque table qui met à jour les données ou génère une liste des différences.

La structure de base derrière le code est la suivante:

  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

Maintenant, la complexité majeure est que votre clause WHERE doit être différente pour chaque champ - les champs de texte doivent être traités différemment des champs numériques et de données. Donc, vous voudrez probablement un SELECT CASE qui écrit votre clause WHERE en fonction du type de champ:

  Select Case fld.Type
    Case dbText, dbMemo
    Case Else
  End Select

Vous voudrez utiliser Nz () pour comparer les champs de texte, mais vous utiliserez Nz (TextField, '') pour cela, tout en utilisant Nz (NumericField, 0) pour les champs numériques ou les champs de date.

Mon exemple de code n'utilise pas réellement la structure ci-dessus pour définir la clause WHERE car il est limité aux champs qui fonctionnent très bien en comparaison concaténée avec un ZLS (champs de texte). Ce qui est écrit en dessous est assez compliqué à lire, mais c’est essentiellement une extension de la structure ci-dessus.

Il a été écrit pour l'efficacité des mises à jour, car il exécute une instruction UPDATE SQL pour chaque champ de la table, ce qui est beaucoup plus efficace que l'exécution d'une instruction UPDATE SQL pour chaque ligne. Si, par contre, vous ne voulez pas faire de mise à jour, mais plutôt une liste des différences, vous pouvez traiter le tout différemment. Mais cela devient assez compliqué en fonction de la sortie,

Si tout ce que vous voulez savoir, c'est si deux MDB sont identiques, vous devriez d'abord vérifier le nombre d'enregistrements dans chaque table, et si vous avez une non-correspondance, vous quittez et dites à l'utilisateur que les MDB ne sont pas le même. Si les montants d'enregistrement sont identiques, vous devez alors vérifier champ par champ, ce qui, à mon avis, est le mieux accompli avec un script SQL écrit colonne par colonne écrit dynamiquement: dès qu'un des résultats SQL SELECTS renvoyé renvoie un ou plusieurs enregistrements, vous annulez et dites à votre utilisateur que les MDB ne sont pas identiques.

La partie compliquée consiste à enregistrer les différences et à en informer l'utilisateur, sans quoi cela rendrait cette publication déjà interminable encore plus longue!

Ce qui suit n'est qu'une partie du code d'un sous-programme plus important qui met à jour la requête sauvegardée qdfOldMembers (à partir de MDB A) avec les données de qdfNewMembers (à partir de MDB B). Le premier argument, strSQL, est une instruction SELECT limitée aux champs que vous souhaitez comparer, tandis que strTmpDB est le chemin / nom de fichier de l'autre MDB (MDB B dans notre exemple). Le code suppose que strTmpDB a déjà créé qdfNewMembers et qdfOldMembers (le code d'origine écrit le QueryDef enregistré à la volée). Cela pourrait tout aussi bien être un nom de table direct (la seule raison pour laquelle j’utilise une requête enregistrée est que les noms de champ ne correspondent pas exactement entre les deux MDB pour lesquels il a été écrit).

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

Code de la fonction varZLSToNull ():

Public Function varZLStoNull(varInput As Variant) As Variant
  If Len(varInput) = 0 Then
     varZLStoNull = Null
  Else
     varZLStoNull = varInput
  End If
End Function

Je ne sais pas si c'est trop complexe pour que cela ait un sens, mais peut-être que ça aidera quelqu'un.

Autres conseils

Vous pouvez essayer AccessDiff (produit payant). Il a la capacité de comparer le schéma, les données et également d'accéder aux objets. Il a une interface graphique et également une interface de ligne de commande.

Divulgation: je suis le créateur de cet outil.

Prenez des copies de texte des tables de la base de données et comparez-les simplement à l’aide de BeyondCompare (ou de tout autre outil de comparaison de texte). Brut mais peut fonctionner!

J'ai une très bonne expérience du comparateur de bases de données . Il est capable de comparer la structure et / ou les données.

Consultez la section Comparaison des bases de données à l'adresse utilitaires, produits et outils tiers de Microsoft Access. , modules, etc. sur mon site Web.

J'ai ajouté "table diff". fonctionnalité à mon utilitaire accepter il n'y a pas si longtemps. Je pense que cette réponse n’aidera pas à résoudre la question initiale, mais elle pourra peut-être être utile à une personne confrontée au même problème à l’avenir.

Si vous voulez savoir si les fichiers sont identiques, alors

fc file1.mdb file2.mdb 

sur une ligne de commande DOS.

Si les fichiers ne sont pas identiques mais que vous pensez qu'ils contiennent les mêmes tables et enregistrements, le moyen le plus simple serait d'écrire rapidement un petit utilitaire qui ouvre les bases de données et parcourt les tables des deux en effectuant une requête hétérogène pour extraire le fichier Diff. entre les deux fichiers.

Certains outils permettent de le faire pour vous, mais ils semblent tous être des partagiciels.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top