9

2 つの ms-access .mdb ファイルを比較して、含まれているデータが両方で同じであることを確認したいと考えています。

これどうやってするの?

4

7 に答える 7

6

私はこの種のことをコードで何度も行ってきましたが、ほとんどの場合、Web サイトに入力されたデータから取得した更新をローカル MDB に適用する必要がありました。あるケースでは、Web サイトは MDB によって駆動され、他のケースでは MySQL データベースでした。MDB の場合はダウンロードしただけで、MySQL の場合は Web サイトでスクリプトを実行してテキスト ファイルをエクスポートし、FTP しました。

ここで重要な点は、ローカル MDB のデータを Web サイトからダウンロードしたデータと比較し、Web サイトで行われた変更を反映するようにローカル MDB を更新することでした (いいえ、単一のデータ ソースを使用することはできませんでした。 - それは私が最初に提案したことでしたが、実現可能ではありませんでした)。

MDB A をローカル データベースと呼び、MDB B を比較のためにダウンロードしているデータベースと呼びましょう。確認する必要があるのは次のとおりです。

  1. MDB A には存在するが MDB B には存在しないレコード。これらは削除の候補になる場合とそうでない場合があります (これは特定のデータによって異なります)。

  2. MDB B には存在するが MDB A には存在しないレコード。これらは MDB B から MDB A に追加します。

  3. 両方に存在するレコード。フィールドごとに比較する必要があります。

手順 1 と 2 は、外部結合を使用して欠落しているレコードを検索するクエリを使用すると、かなり簡単に実行できます。ステップ 3 にはいくつかのコードが必要です。

コードの背後にある原則は、両方の MDB のすべてのテーブルの構造が同一であるということです。したがって、DAO を使用して TableDefs コレクションをウォークし、レコードセットを開き、fields コレクションをウォークして、データを更新するか、相違点のリストを出力する各テーブルの各列で SQL ステートメントを実行します。

コードの背後にある基本的な構造は次のとおりです。

  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

ここでの主な複雑さは、各フィールドの WHERE 句が異なる必要があることです。テキスト フィールドは、数値フィールドやデータ フィールドとは異なる方法で処理する必要があります。したがって、おそらく、フィールド タイプに基づいて WHERE 句を記述する SELECT CASE が必要になるでしょう。

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

Nz() を使用してテキスト フィールドを比較する必要がありますが、そのためには Nz(TextField,'') を使用し、数値フィールドまたは日付フィールドには Nz(NumericField,0) を使用します。

私のコード例では、上記の構造を実際に使用して WHERE 句を定義していません。これは、連結された ZLS (テキスト フィールド) と比較して非常にうまく機能するフィールドに限定されているためです。以下は非常に読みにくいですが、基本的には上記の構造を拡張したものです。

これは、テーブルのフィールドごとに SQL UPDATE を実行するため、更新の効率化のために作成されました。これは、行ごとに SQL UPDATE を実行するよりもはるかに効率的です。一方、更新を行いたくないが、相違点のリストが必要な場合は、全体を別の方法で処理することができます。しかし、それは出力によってはかなり複雑になります。

2 つの MDB が同一かどうかだけを知りたい場合は、最初に各テーブルのレコード数を確認し、一致しないものが 1 つある場合は終了して、MDB が同じではないことをユーザーに伝えます。レコード数が同じ場合は、フィールドごとにチェックする必要があります。これは、動的に記述された列ごとの SQL で最もよく達成されると思います。結果の SQL SELECTS の 1 つが 1 つ以上のレコードを返すとすぐに、中止します。 MDB が同一ではないことをユーザーに伝えます。

複雑な部分は、違いを記録してユーザーに通知したい場合ですが、それを行うと、このすでに途方もない投稿がさらに長くなります!

以下は、保存されたクエリ qdfOldMembers (MDB A から) を qdfNewMembers (MDB B から) からのデータで更新する、より大きなサブルーチンのコードの一部です。最初の引数 strSQL は、比較するフィールドに限定された SELECT ステートメントです。strTmpDB は、他の MDB (この例では MDB B) のパス/ファイル名です。このコードは、strTmpDB に qdfNewMembers と qdfOldMembers が既に作成されていることを前提としています (元のコードは、保存された QueryDef をオンザフライで書き込みます)。簡単に直接のテーブル名にすることもできます (保存されたクエリを使用する唯一の理由は、それが作成された 2 つの MDB 間でフィールド名が正確に一致しないためです)。

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

関数 varZLSToNull() のコード:

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

それが複雑すぎて意味をなさないかどうかはわかりませんが、誰かの助けになるかもしれません。

于 2008-10-27T21:17:31.963 に答える
5

AccessDiff(有料製品)を試すことができます。スキーマ、データを比較し、オブジェクトにアクセスする機能があります。GUIとコマンドラインインターフェイスがあります。

開示:私はこのツールの作成者です。

于 2011-09-05T19:15:42.003 に答える
2

Cross-Database Comparator の使用経験は非常に豊富です。構造やデータを比較することができます。

于 2008-10-27T10:45:02.800 に答える
2

データベース テーブルのテキスト ダンプを取得し、BeyondCompare (またはその他のテキスト比較ツール) を使用して、ダンプされたテキスト ファイルを単純に比較します。粗雑ですが動作します!

于 2008-10-27T10:37:36.497 に答える
1

私の Web サイトのMicrosoft Access サード パーティのユーティリティ、製品、ツール、モジュールなどのページにある Access データベースの比較セクションを参照してください。

于 2009-11-30T21:39:49.387 に答える
0

少し前にaccdbmergeユーティリティに「テーブル差分」機能を追加しました。この回答は元の質問の解決には役立たないと思いますが、将来同じ問題に直面した人にとっては役立つかもしれません。

于 2012-03-04T20:41:44.733 に答える
-4

ファイルが同一かどうかを知りたい場合は、

fc file1.mdb file2.mdb 

DOS コマンドラインで。

ファイルが同一ではないが、同じテーブルとレコードが含まれていると思われる場合、最も簡単な方法は、両方のデータベースを開き、両方のテーブルを循環して異種クエリを実行し、2 つの間の差分を抽出する小さなユーティリティをすばやく作成することです。ファイル。

これを行うツールがいくつかありますが、それらはすべてシェアウェアのようです。

于 2008-10-27T10:12:13.100 に答える