Posso confrontare due file ms-access? [chiuso]
Domanda
Voglio confrontare due file .mdb con accesso ms per verificare che i dati che contengono siano gli stessi in entrambi.
Come posso farlo?
Soluzione
Ho fatto questo genere di cose nel codice molte, molte volte, soprattutto nei casi in cui un MDB locale aveva bisogno di applicare gli aggiornamenti a esso tratto dai dati inseriti su un sito Web. In un caso il sito Web era gestito da un MDB, in altri era un database MySQL. Per MDB, l'abbiamo appena scaricato, per MySQL, abbiamo eseguito script sul sito Web per esportare e file di testo FTP.
Ora, il punto principale è che volevamo confrontare i dati nell'MDB locale con i dati scaricati dal sito Web e aggiornare l'MDB locale per riflettere le modifiche apportate sul sito Web (no, non è stato possibile utilizzare un singolo origine dati: è stata la prima cosa che ho suggerito, ma non è stato possibile).
Chiamiamo MDB A il tuo database locale e MDB B quello che stai scaricando per il confronto. Quello che devi controllare è:
-
record esistenti in MDB A ma non in MDB B. Questi possono o meno essere candidati alla cancellazione (questo dipenderà dai tuoi dati particolari).
-
record esistenti in MDB B ma non in MDB A. Questi verranno aggiunti da MDB B a MDB A.
-
record esistenti in entrambi, che dovranno essere confrontati campo per campo.
I passaggi n. 1 e n. 2 sono abbastanza facilmente realizzati con query che utilizzano un join esterno per trovare i record mancanti. Il passaggio 3 richiede del codice.
Il principio alla base del codice è che la struttura di tutte le tabelle in entrambi gli MDB è identica. Quindi, si utilizza DAO per eseguire il walk della raccolta TableDefs, aprire un recordset e camminare la raccolta dei campi per eseguire un'istruzione SQL su ciascuna colonna di ogni tabella che aggiorna i dati o genera un elenco delle differenze.
La struttura di base dietro il codice è:
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
Ora, la maggiore complessità qui è che la clausola WHERE per ciascun campo deve essere diversa: i campi di testo devono essere trattati in modo diverso dai campi numerici e di dati. Quindi probabilmente vorrai un SELEZIONA CASO che scrive la tua clausola WHERE in base al tipo di campo:
Select Case fld.Type
Case dbText, dbMemo
Case Else
End Select
Ti consigliamo di usare Nz () per confrontare i campi di testo, ma per questo utilizzeresti Nz (TextField, ''), mentre usi Nz (NumericField, 0) per campi numerici o campi data.
Il mio codice di esempio in realtà non utilizza la struttura sopra per definire la clausola WHERE perché è limitata ai campi che funzionano molto bene confrontando concatenati con uno ZLS (campi di testo). Quello che segue è piuttosto complicato da leggere, ma è fondamentalmente un'espansione della struttura sopra.
È stato scritto per l'efficienza degli aggiornamenti, poiché esegue un aggiornamento SQL per ogni campo della tabella, che è molto più efficiente dell'esecuzione di un aggiornamento SQL per ogni riga. Se, d'altra parte, non vuoi fare un aggiornamento, ma vuoi un elenco delle differenze, potresti trattare l'intera cosa in modo diverso. Ma questo diventa piuttosto complicato a seconda dell'output,
Se tutto ciò che vuoi sapere è se due MDB sono identici, dovresti prima controllare il numero di record in ciascuna tabella e se hai una non corrispondenza, esci e dici all'utente che gli MDB non lo sono lo stesso. Se i conteggi dei record sono gli stessi, allora devi controllare campo per campo, che credo sia meglio realizzare con SQL colonna per colonna scritto in modo dinamico - non appena uno degli SQL SELECTS risultanti restituisce 1 o più record, interrompi e comunica al tuo utente che gli MDB non sono identici.
La parte complicata è se si desidera registrare le differenze e informare l'utente, ma approfondire ciò renderebbe questo post già interminabile ancora più lungo!
Quello che segue è solo una parte del codice di una subroutine più grande che aggiorna la query salvata qdfOldMembers (da MDB A) con i dati da qdfNewMembers (da MDB B). Il primo argomento, strSQL, è un'istruzione SELECT limitata ai campi che si desidera confrontare, mentre strTmpDB è il percorso / nome file dell'altro MDB (MDB B nel nostro esempio). Il codice presuppone che strTmpDB abbia già creato qdfNewMembers e qdfOldMembers (il codice originale scrive al volo il QueryDef salvato). Potrebbe essere altrettanto facile essere nomi di tabella diretti (l'unica ragione per cui utilizzo una query salvata è perché i nomi dei campi non corrispondono esattamente tra i due MDB per cui è stato scritto).
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
Codice per la funzione varZLSToNull ():
Public Function varZLStoNull(varInput As Variant) As Variant
If Len(varInput) = 0 Then
varZLStoNull = Null
Else
varZLStoNull = varInput
End If
End Function
Non so se sia troppo complesso per avere un senso, ma forse aiuterà qualcuno.
Altri suggerimenti
Puoi provare AccessDiff (prodotto a pagamento). Ha la capacità di confrontare lo schema, i dati e anche gli oggetti di accesso. Ha una GUI e anche un'interfaccia a riga di comando.
Divulgazione: sono il creatore di questo strumento.
Prendi i dump di testo delle tabelle del database e confronta semplicemente i file di testo scaricati usando BeyondCompare (o qualsiasi altro strumento di confronto del testo). Crudo ma può funzionare!
Ho un'ottima esperienza con Comparatore tra database diversi . È in grado di confrontare struttura e / o dati.
Consulta la sezione Confronta i database di Access in Utilità, prodotti e strumenti di terze parti di Microsoft Access , moduli, ecc. sul mio sito Web.
Ho aggiunto " table diff " funzione della mia accdbmerge non molto tempo fa. Credo che questa risposta non aiuterà a risolvere la domanda originale, ma potrebbe essere utile per qualcuno che dovrà affrontare lo stesso problema in futuro.
Se vuoi sapere se i file sono identici, allora
fc file1.mdb file2.mdb
su una riga comandi DOS.
Se i file non sono identici ma si sospetta che contengano le stesse tabelle e record, il modo più semplice sarebbe quello di scrivere rapidamente una piccola utility che apre entrambi i database e scorre le tabelle di entrambi eseguendo una query eterogenea per estrarre il Diff tra i due file.
Ci sono alcuni strumenti là fuori che lo faranno per te, ma sembrano tutti shareware.