我可以比较两个ms访问文件吗?

时间:2008-10-27 09:49:27

标签: ms-access ms-office

我想比较两个ms-access .mdb文件,以检查它们包含的数据是否相同。

我该怎么做?

7 个答案:

答案 0 :(得分:6)

我已经在代码中做了很多次这样的事情,主要是在本地MDB需要从网站上输入的数据中应用更新的情况下。在一个案例中,该网站由MDB驱动,在其他情况下,它是一个MySQL数据库。对于MDB,我们只是下载它,对于MySQL,我们在网站上运行脚本以导出和FTP文本文件。

现在,重点是我们想要将本地MDB中的数据与从网站下载的数据进行比较,并更新本地MDB以反映在网站上所做的更改(不,不可能使用单个数据源 - 这是我建议的第一件事,但这不可行。)

让我们将MDB A称为您的本地数据库,将MDB B称为您要下载的用于比较的数据库。您需要检查的是:

  1. MDB A中存在但不存在于MDB B中的记录。这些记录可能会或可能不会被删除(这取决于您的特定数据)。

  2. MDB B中存在但MDB A中不存在的记录。这些记录将从MDB B追加到MDB A.

  3. 两者中都存在的记录,需要逐个字段进行比较。

  4. 使用外部联接查找缺失记录的查询可以非常轻松地完成步骤#1和#2。第3步需要一些代码。

    代码背后的原理是两个MDB中所有表的结构都是相同的。因此,您使用DAO来遍历TableDefs集合,打开记录集,并遍历字段集合以在每个表的每列上运行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更有效。另一方面,如果您不想进行更新,但想要一个差异列表,则可能会以不同的方式处理整个事情。但这取决于输出,这变得非常复杂,

    如果您只想知道两个MDB是否相同,您首先要检查每个表中的记录数,如果您有一个不匹配,则退出并告诉用户MDB不是相同。如果记录计数是相同的,那么你必须逐字段检查,我认为最好用动态编写的逐列SQL完成 - 只要其中一个结果SQL SELECTS返回1个或多个记录,就会中止并告诉您的用户MDB不相同。

    复杂的部分是,如果你想记录差异并通知用户,但进入那个将使这个已经无休止的帖子更长!

    以下是来自较大子例程的一部分代码,该子例程使用来自qdfNewMembers(来自MDB B)的数据更新已保存的查询qdfOldMembers(来自MDB A)。第一个参数strSQL是一个SELECT语句,仅限于您要比较的字段,而strTmpDB是另一个MDB的路径/文件名(在我们的示例中为MDB B)。该代码假定strTmpDB已经创建了qdfNewMembers和qdfOldMembers(原始代码动态写入保存的QueryDef)。它可以很容易地直接表名(我使用保存查询的唯一原因是因为字段名在它所写的两个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
    

    我不知道这是否太复杂而无法理解,但也许它会帮助某人。

答案 1 :(得分:5)

您可以尝试AccessDiff(付费产品)。它能够比较模式,数据以及访问对象。它有一个GUI和一个命令行界面。

披露:我是此工具的创建者。

答案 2 :(得分:2)

获取数据库表的文本转储,并使用BeyondCompare(或任何其他文本比较工具)简单地比较转储的文本文件。原油但可以工作!

答案 3 :(得分:2)

我对Cross-Database Comparator有很好的经验。它能够比较结构和/或数据。

答案 4 :(得分:1)

请参阅我网站Microsoft Access third party utilities, products, tools, modules, etc.页面上的比较访问数据库部分。

答案 5 :(得分:0)

我不久前在我的accdbmerge实用程序中添加了“表差异”功能。 我相信这个答案无助于解决原始问题,但对将来遇到同样问题的人来说可能会有所帮助。

答案 6 :(得分:-4)

如果您想知道文件是否相同,那么

fc file1.mdb file2.mdb 

在DOS命令行上。

如果文件不相同但您怀疑它们包含相同的表和记录,那么最简单的方法是快速编写一个小实用程序,打开两个数据库并循环执行异构查询以提取Diff的表两个文件之间。

有一些工具会为你做这件事,但它们似乎都是共享软件。