当前位置:  开发笔记 > 后端 > 正文

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

如何解决《我可以比较两个ms访问文件吗?》经验,为你挑选了2个好方法。

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

我怎样才能做到这一点?



1> David-W-Fent..:

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

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

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

    存在于MDB A但不存在于MDB B中的记录.这些记录可能是也可能不是删除的候选者(这取决于您的特定数据).

    存在于MDB B但不存在于MDB A中的记录.这些记录将从MDB B附加到MDB A.

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

使用外部联接查找缺失记录的查询可以非常轻松地完成步骤#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

我不知道这是否太复杂有意义,但也许它会帮助某人.



2> Greg Finzer..:

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

披露:我是这个工具的创造者.


您应该在答案中说明您是此工具的创建者,而不是将其留给某人来关注该链接.全面披露可提高可信度
我建立了AccessDiff来支付我的三个孩子的大学教育.我希望大学也是免费的.;)
推荐阅读
罗文彬2502852027
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有