Es kommt ziemlich häufig vor, dass Sie den Inhalt von zwei Tabellen vergleichen brauchen.
· Daten aus verschiedenen Quellen werden zusammengefügt und dabei müssen doppelte Schlüsselwerte vermieden werden.
· Unterschiede zwischen Tabellen, die den Stand zu verschiedenen Zeitpunkten darstellen, werden ausgewertet.
· Bei der Entwicklung stellt der Vergleich der Daten vor und nach einer Programmänderung eine geeignete Testmethode dar. Sie können auch eine geänderte Abfrage in temporären Tabellen abspeichern und mehrere Versionen miteinander vergleichen.
Der Vorgang besteht grundsätzlich aus zwei Hauptaufgaben:
· Schlüssel-Felder werden verglichen. Dabei wird die Frage beantwortet, welche Datensätze in einer Tabelle vorhanden sind und in der anderen fehlen und umgekehrt.
· In den Datensätzen mit Schlüsselwerten, die in beiden Tabellen gleich sind, können auch die Nicht-Schlüssel-Felder miteinander verglichen werden.
Die obengenannten Aufgaben sind problemlos mit Abfragen zu lösen. Auch wenn die Arbeit mit der MS-Access-Oberfläche zum Abfragenentwurf durchaus einfach ist, stellt der auf diese Art und Weise durchgeführte Tabellenvergleich doch einen unnötigen Aufwand dar. Die zu erstellenden Abfragen sind meistens nur für einen einmaligen Gebrauch bestimmt und müsen daher nicht dauerhaft in der Applikation gespeichert werden.
Ein allgemein einsetzbares Tool, dass die notwendigen Abfragen automatisch erstellt spart eine Menge Zeit.
Alle Bedienungselemente sind in einem einzigen Hauptformular untergebracht. Die linke und rechte Hälfte sind praktisch gleich und stellen die verglichenen Elemente der beiden Tabellen dar. Die Bedienung erfolgt logisch von der Datenbankauswahl oben bis zu der Ergebnisanzeige unten.
Die Schaltfläche mit dem Fragenzeichen (links oben) öffnet ein Fenster mit einer Kurzanleitung.
Abbildung -1: Haupformular des Programms
Die verglichenen Tabellen können in zwei unterschiedlichen oder in der gleichen Datenbank gespeichert werden. Die Schaltflächen Durchsuchen ermöglichen die Auswahl mit Hilfe des Standard-Öffnen-Dialogs. Der Pfad und Name der ausgewählten Datenbank wird im darunterliegenden Textfeld angezeigt.
Die Schlaltfläche DB1=DB2 überträgt die gleiche Datenbankangabe von der linken in die rechte Hälfte des Formulars ohne dass das Öffnen-Dialog angezeigt werden muß. Sie ist für den Fall bestimmt, dass beide Tabellen in der gleichen Datenbank liegen.
Nachdem die Datenbank ausgewählt wird, wird automatisch das Combobox mit allen vorhandenen Tabellennamen befüllt und heruntergeklappt. Die verglichenen Tabellen lassen sich auswählen. Es muß sich dabei nicht um zwei unterschiedliche Tabellen handeln, auch ein Vergleich von verschiedenen Feldern der gleichen Tabelle ist problemlos möglich. Die Verknüpfung zwischen den Schlüsselfeldern muß dabei definiert werden auch wenn die Anzeige der fehlenden Datensätze in diesem Fall sinnlos ist.
Nach der Tabellenauswahl werden die darunterliegenden Listboxe mit allen vorhandenen Feldnamen befüllt.
Die Tabellenfelder können mit Hilfe von Schaltflächen mit Symbolen >, < und >> von den äußeren in die inneren Listboxe übertragen werden. Dabei bleiben sie (im Gegenstatz zum Standard-Verhalten in diversen Access-Assistenten) in den äußeren Listboxen erhalten. So ist es theoretisch möglich (auch wenn wahrscheinlich nicht oft gefragt), dass ein Feld sowohl als ein Schlüssel-, als auch als ein Nicht-Schlüssel-Feld eingesetzt wird, damit sein Wert mit einem anderen Feld verglichen werden kann.
Die Inhalte der inneren Listboxe werden beim Erstellen der Ergebnisabfragen berücksichtigt. Die Reihenfolge der Felder ist dabei wichtig. Es werden immer die gegenüberliegenden Felder miteinander verglichen. Dabei ist es zu beachten, dass der Datentyp der zugehörigen Felder gleich sein muß.
Die Felder, die in die oberen zwei Listboxe Verknüpfte Schlüsselfelder übertragen werden, bilden die Verknüpfung (JOIN) zwischen den Tabellen.
Die unteren zwei Listboxe Verglichene Felder enthalten die Felder, die in den Datensätzen verglichen werden, bei denen die Inhalte der Schlüsselfelder gleich sind.
Die Schaltflächen im unteren Teil des Formulars zeigen alle möglichen Ergebnisabfragen an. Sie werden aktiviert oder deaktiviert je nach der Anzahl der ausgewählten Felder beider Tabellen. Die Strukturen der Abfragen werden aus der Auswahl nach folgendem Schema gebildet:
· Tabelle 1, bzw. Tabelle 2 enthalten alle verknüpften und verglichenen Felder der ersten, bzw. der zweiten Tabelle
· Fehlende in der Tabelle 1, bzw. 2 enthalten alle verknüpften und verglichenen Felder der Datensätze, derer Schlüsselwerte in der anderen Tabelle nicht vorkommen.
· Gleiche Werte enthalten alle verknüpften und verglichenen Felder der Datensätze einer Tabelle, die alle gleich mit den Feldern der anderen Tabelle sind.
· Unterschiedliche Werte enthalten die verknüpften Felder einer Tabelle und die verglichenen Felder beider Tabellen. Es werden die Datensätze angezeigt, die mindestens in einem Feld unterschiedlich sind.
Für die Erhöhung der Bedienungskomforts sind im Makro Tastaturbelegung drei Tastenkombination (Hot-Keys) definiert:
Tastenkombination |
Aktion |
<Strg>A |
Fenster maximieren |
<Strg>B |
Fenster wiederherstellen |
<Strg>Q |
Hauptformular anzeigen |
Tabelle -1: Implementierte Hot-Keys
Zur Auswahl der Datenbanken wird im Programm das ActiveX-Steuerelement CommonDialog eingesetzt. Das Makro AutoExec startet die Funktion ProgrammStart(), die die Referenz zu diesem Objekt überprüft.
...
On Error GoTo Err_ProgrammStart
Set ref = Application.References("MSComDlg")
...
Err_ProgrammStart:
...
g.OCXused = False
Sollte das ActiveX-Steuerelement nicht richtig registriert sein, wird eine Meldung ausgegeben und die globale Variable OCXused auf False gesetzt.
Beim Laden des Hauptformulars wird die Prozedur FormInit für beide Formularhälften aufgerufen. Sollte das ActiveX-Steuerelements nicht verfügbar sein, werden die Schaltflächen Durchsuchen deaktiviert. In diesem Fall müssen für die Auswahl der Datenbanken ihre Pfade und Namen in den Textfeldern manuell eingegeben werden.
Sub Form_Load()
FormInit "1"
FormInit "2"
Me.cmdMDB1.Enabled = g.OCXused
Me.cmdMDB2.Enabled = g.OCXused
Die Prozedur wird mit einem Parameter aufgerufen, damit sie auch nur für eine Formularhälfte eingesetzt werden kann. Die Verknüpfung zu der verglichenen Tabelle wird gelöscht und die Steuerelemente für die Tabellen- und Feldauswahl initialisiert. Für das Löschen der Inhalte der inneren Listboxe werden die Ereignis-Prozeduren der Schaltflächen "<<", bzw. ">>" aufgerufen.
Sub FormInit(t$)
TableDelete "T" + t
Me.Controls("cboTab" + t) = Null
Me.Controls("lstFeld" + t).Requery
If t = "1" Then
cmdJoin1Init_Click
cmdComp1Init_Click
Else
cmdJoin2Init_Click
...
TableDelete ist eine fehlertolerante Prozedur, die eine Tabelle oder eine Tabellenverknüpfung in der aktuellen Datenbank löscht.
Sub TableDelete(Name$)
Dim tdf As TableDef
For Each tdf In CurrentDb.TableDefs
If tdf.Name = Name Then
CurrentDb.TableDefs.delete Name
Exit Sub
End If
Next tdf
End Sub
Die meisten Selektionsvorgänge sind für beide Tabellen (Formularhälften) identisch und werden aus diesem Grund nur für die erste Tabelle (linke Hälfte) erklärt.
Die Schaltfläche Durchsuchen ruft die Funktion GetDatabaseName() auf, die das Dialog öffnet und den ausgewählten Pfad und Datenbanknamen in das Textfeld txtMDB1 schreibt. Durch den Aufruf der Ereignisprozedur AfterUpdate des Textfeldes wird der weitere Programmablauf gleich wie nach der manuellen Eingabe in das Textfeld.
Sub cmdMDB1_Click()
txtMDB1 = GetDatabaseName()
txtMDB1_AfterUpdate
End Sub
Funktion GetDatabaseName() öffnet das ActiveX-Steuerelement CommonDialog, das im Steuerelement ocxOpen untergebracht ist und liefert den ausgewählten Pfad und Datenbanknamen.
|
Function GetDatabaseName()
With Me.ocxOpen
.DialogTitle = "Wählen Sie die Datenbank
aus"
.Filter = "Access Datenbanken
(*.mdb)|*.mdb|MDE Dateien(*.mde)|*.mde|"
.FileName = ""
.ShowOpen
GetDatabaseName = .FileName
...
Nachdem eine Datenbank im Öffnen-Dialog oder durch die manuelle Eingabe im Textfeld ausgewählt wurde, wird das Combobox cboTab1 für die Auswahl von Tabellen befüllt und heruntergeklappt. Sein Inhalt wird der Systemtabelle MSysObjects entnommen. Die Einträge mit Type=1, die nicht mit "MSys" beginnen, stellen die normalen Tabellen dar.
Sub txtMDB1_AfterUpdate()
...
cboTab1.RowSource = "SELECT name FROM [" & txtMDB1 & "].msysobjects WHERE (type=1) and not name like 'MSys*' ORDER BY name;"
Me.cboTab1.Enabled = True
Me.cboTab1.SetFocus
Me.cboTab1.Dropdown
...
Nach der Auswahl der Tabelle im Combobox cboTab1 wird die Prozedur TabConnect aufgerufen, die die Verknüpfung zu der gewünschten Tabelle erstellt. Die Verknüpfungen bekommen die Namen "T1", bzw "T2". Mit diesen Namen werden die Tabellen in den generierten Abfragen referenziert. Die Prozedur wird mit dem gleichen Parameter wie FormInit aufgerufen, der die erste oder zweite Tabelle bezeichnet. Am Ende der Prozedur wird das Listbox, das die verfügbaren Tabellenfelder anzeigt, initialisiert. Dieses Steuerelement muß nicht näher erklärt werden, die notwendige Funktionalität wird nur durch das Einstellen der Eigenschaften Herkunftstyp auf Feldliste und Datenherkunft auf die Tabelle T1, bzw. T2 erreicht.
Sub TabConnect(t$)
...
TableDelete "T" + t
Set tdf = db.CreateTableDef("T" + t)
tdf.Connect = ";Database=" +
Me.Controls("txtMDB" + t)
tdf.SourceTableName =
Me.Controls("cboTab" + t)
db.TableDefs.Append tdf
Me.Controls("lstFeld" + t).Requery
...
Auf dem Formular befinden sich vier innere Listboxe. In diesen werden die verknüpften und verglichenen Felder beider Tabellen angezeigt. Die ausgewählten Feldnamen werden in Datenfeldern (Arrays) gespeichert. Pro jedes Listbox wird ein Array definiert.
Für das Erstellen der Ergebnisabfragen sind eigentlich die Inhalte der Arrays relevant. Die Listboxe werden dabei nicht abgefragt uns stellen nur die Präsentation der Auswahl dar.
Die vier Listboxe heißen lstJoin1 und lstJoin2 für die verknüpften und lstComp1 und lstComp2 für die verglichenen Felder. Die gleiche Funktionalität ist viermals vorhanden, aus diesem Grund werden die Programmteile nur einmal für das Listbox lstJoin1 beschrieben. Zuerst die Übersicht der Namen der zusammenhängenden Objekte:
Objekt |
Bedeutung |
lstJoin1 |
inneres Listbox |
arrJoin1 |
zugehöriges Array |
cmdJoin1on |
Feld(er) einfügen |
cmdJoin1off |
Feld(er) entfernen |
cmdJoin1init |
alle Feld(er) entfernen |
Tabelle -2: Objekte für die Auswahl der verknüpften Felder der ersten Tabelle
Die Ereignis-Prozeduren der drei o.g. Schaltflächem pro Listbox müssen nur die Arrays richtig befüllen. Die Anzeige der Inhalte der Arrays in den Listboxen erfolgt automatisch durch die Funktion FillLstFromArray(). Ihr Name wird gleich für alle vier Listboxe in der Eigenschaft Herkunftstyp eingetragen. Die Funktion wird an dieser Stelle nicht ausführlich beschrieben, weil sie grundsätzlich der Standardlösung entspricht, die in der Hilfe unter "RowSourceType-Eigenschaft " zu finden ist.
Die Funktion FillSelArr() übernimmt die markierten Einträge (Feldnamen) des äußeren Listboxes in das entsprechende Array des inneren Listboxes. Sie wird beim Aktivieren zum Beispiel der Schaltfläche cmdJoin1on mit zwei Parametern aufgerufen:
· lst das äußere Listbox
· arr Array des inneren Listboxes
Bei jedem Aufruf wird in allen Elementen des äußeren Listboxes die Eigenschaft Selected überfprüft und die markierten Feldnamen an Ende des Arrays angehängt.
Function FillSelArr(lst As Control,
arr As Variant)
...
For i = 0 To lst.ListCount - 1
If lst.Selected(i) Then
If Len(arr(0)) > 0 Then
ReDim Preserve arr(UBound(arr) + 1)
End If
arr(UBound(arr)) = lst.Column(0, i)
End If
Next i
...
Die Funktion ArrElemDelete() wird aufgerufen, wenn die Schaltfläche zum Entfernen von ausgewählten Feldern aktiviert wird. Sie hat zwei Parameter, die ähnliche Bedeutung haben, wie bei FillSellArr(). Diesmal wird aber nur das innere Listbox behandelt.
· lst das innere Listbox
· arr Array des inneren Listboxes
Die Elemente des inneren Listboxes werden vom Ende auf die Eigenschaft Selected überfprüft und für die markierten wird die Funktion zum Enfernen eines Array-Elements OneElemDelete() aufgerufen.
Sub ArrElemDelete(lst As Control,
arr As Variant)
For i = lst.ListCount - 1 To 0 Step -1
If lst.Selected(i) Then
OneElemDelete arr, i
End If
Next i
Die Funktion ArrElemDelete() hat zwei Parameter:
· arr Array des inneren Listboxes
· delind Index des gelöschten Elements
Zuerst werden alle Elemente ab dem gelöschten um eine Position zum Anfang verschoben und dann die Dimension des Arrays um 1 verringert.
Dabei gibt es ein kleines Problem – wenn alle ausgewählten Felder entfernt werden, muß im Array doch ein Element mit dem Index 0 erhalten bleiben. In dem Fall wird das Array nicht redimensioniert, sondern das erste Element geleert. Die Länge dieses ersten Elements wird beim Erstellen der Ergebnisabfragen überprüft, um festzustellen, ob mindestens ein Feld für den jeweiligen Teil des SQL-Ausdrucks ausgewählt wurde.
Sub OneElemDelete(arr As Variant, delind%)
...
For i = delind To UBound(arr) - 1
arr(i) = arr(i + 1)
Next i
If UBound(arr) > 0 Then
ReDim Preserve arr(UBound(arr) - 1)
Else
arr(0) = ""
End If
...
Wenn alle ausgewählten Felder aus dem inneren Listbox entfernt werden sollen, reicht es einfach, nur das zugehörige Array ohne Preserve zu redimensionieren. Damit wird es vollständig initialisiert und das innere Listbox geleert.
Sub cmdJoin1Init_Click()
ReDim arrJoin1(0)
...
In der Ereignisprozedur jeder Schaltfläche, die die Feldauswahl beeinflußt (insgesamt 12 Stück), müssen noch zwei Aktionen durchgeführt werden.
· das entsprechende innere Listbox wird neu angezeigt, damit die Veränderung sichtbar ist
· die Fuktion ActionEnable() wird aufgerufen, damit die Schaltflächen zur Anzeige der Vergleichsergebnisse entsprechend der Auswahl aktiviert oder deaktiviert werden
So schaut also beispielweise die komplette Ereignisprozedur der Schaltfläche zur Auswahl eines verknüpften Schlüssefeldes der ersten Tabelle aus:
Sub cmdJoin1on_Click()
FillSelArr lstFeld1, arrJoin1
lstJoin1.Requery
ActionEnable
End Sub
Wenn die Arrays mit ausgewählten Feldern richtig befüllt sind, können die Ergebnisse des Tabellenvergleichs ausgewertet werden.
Die dynamisch erstellten Ergenisabfragen haben die gleichen Namen wie die Aufschriften auf den im unteren Teil des Formulars angebrachten Schaltflächen:
Schaltfläche |
Abfrage |
cmdTab1 |
Tabelle 1 |
cmdTab2 |
Tabelle 2 |
cmdTab1more |
Fehlende in der Tabelle 2 |
cmdTab2more |
Fehlende in der Tabelle 1 |
cmdFeldEq |
Gleiche Werte |
cmdFeldDiff |
Unterschiedliche Werte |
Tabelle -3: Schaltflächen und Abfragen für die Anzeige der Ergebnisse
Das Erstellen von Abfragen ist nur dann sinnvoll, wenn auch die notwendigen Felder ausgewählt sind und die Anzahl der Felder in beiden verglichenen Tabellen gleich sind. Durch das Aktivieren und Deaktivieren von Ergebnis-Schaltflächen wird der Anwender auf die unvollständige Auswahl sofort aufmerksam gemacht.
Die Aufgabe wird mit der Prozedur ActionEnable() gelöst, die in der Ereignisprozedur jeder Schaltfläche, die die Feldauswahl beeinflußt, aufgerufen wird. In der Funktion muß sowohl die Anzahl der Array-Elemente als auch die Länge des ersten Elements überprüft werden (siehe oben).
j1 = UBound(arrJoin1)
... j2, c1, c2 dtto
ej1 = (Len(arrJoin1(0)) = 0)
... ej2, ec1, ec2 dtto
Me.cmdTab1.Enabled = Not ej1 Or Not ec1
Me.cmdTab1more.Enabled =
Not ej1 And Not ej2 And (j1 = j2)
Me.cmdFeldDiff.Enabled =
Me.cmdTab1more.Enabled
And Not ec1 And Not ec2 And (c1 = c2)
Für die Anzeige jedes Ergebnisses des Tabellenvergleichs wird der gleiche Vorgang angewendet:
· aus den Feldnamen, die in den Selektion-Arrays gespeichert sind, wird der notwendige SQL-Ausdruck erstellt
· dieser SQL-Ausdruck wird der gewünschten Abfrage zugewiesen
· die Abfrage wird sofort geöffnet
Die Prozedur QueryDefOpen erledigt die letzten zwei Aufgaben des oben angeführten allgemeinen Vorgangs. Sie wird mit zwei Parametern aufgerufen:
· qryname Name der Abfrage
· sqlstr der SQL-Ausdruck
In dieser Funktion ist auch eine Fehlerbehandlung implementiert. Nachdem die Abfrage nicht ausgeführt werden kann (z.B. bei inkompatiblen Datentypen der verglichenen Felder), wird die Access-interne Fehlermeldung angezeigt.
Sub QueryDefOpen(qryname$, sqlstr$)
On Error GoTo Err_QueryDefOpen
Dim qdf As QueryDef
Set qdf = CurrentDb.QueryDefs(qryname)
qdf.SQL = sqlstr
qdf.Close
DoCmd.OpenQuery (qryname)
Exit_QueryDefOpen:
Exit Sub
Err_QueryDefOpen:
MsgBox Error
Resume Exit_QueryDefOpen
End Sub
Damit das Erstellen vom SQL-Ausdruck für einzelne Aufgaben des Vergleichs weitgehend modularisiert werden kann, werden SQL-Teilfunktionen eingesetzt, die die Feldausdrücke aufgrund der Inhalte der Selektions-Arrays zusammenbilden. Zur Erinnerung: Die Abkürzung Join betrifft die verknüpften, Comp die verglichenen Felder.
Die aus den Arrays übernommen Feldnamen werden in eckige Klammern eingeschlossen. Es ist für den Fall notwendig, wenn sie z.B. Leerzeichen enthalten, damit es nicht zu einem Syntaxfehler in SQL kommt.
Die Array-Elemente werden in einer Schleife abgearbeitet und mit Komma getrennt, bzw. die einzelnen Vergleichsoperationen mit dem logischen Operator AND oder OR verbunden. Für die richtige Syntax des gesamten SQL-Ausdruck wird vor dem Verlassen der Funktion aus dem gebildeten Ausdruck das letzte Zeichen oder Wort weggeschnitten.
Die Rückgabewerte dieser Teilfunktionen werden dann in der Ereignis-Prozedur OnClick der jeweiligen Schaltfläche mit Hilfe der zusätzlichen SQL-Anweisungen zum fertigen SQL-Ausdruck der Ergebnisabfrage zusammengefasst und an die Funktion QuryDefOpen() als Parameter übergeben.
Die Funktion SQL_JoinComp() liefert eine Auflistung der Feldnamen der verknüpften und verglichenen Felder einer Tabelle. Diese Auflistung wird als Teil der SELECT-Anweisung verwendet. Die Nummer der Tabelle (1 oder 2) wird als Parameter tabnum übergeben.
Function SQL_JoinComp(tabnum%) As String
...
If tabnum = 1 Then
arrj = arrJoin1
arrc = arrComp1
Else
...
If Len(arrj(0)) > 0 Then
For i = 0 To UBound(arrj)
s = s & "T" & CStr(tabnum) &
".[" & Trim$(arrj(i)) & "],"
Next i
End If
If Len(arrc(0)) > 0 Then
...
SQL_JoinComp = Left$(s, Len(s) - 1)
Die Funktion SQL_Joins() liefert eine Auflistung der verknüpften Felder beider Tabellen. Sie wird im ON-Ausdruck der JOIN-Anweisung eingesetzt.
Function SQL_Joins() As String
For i = 0 To UBound(arrJoin1)
s = s & "(T1.[" & Trim$(arrJoin1(i)) & "]="
& "T2.[" & Trim$(arrJoin2(i)) & "]) AND "
Next i
SQL_Joins = Left$(s, Len(s) - 5)
Die Funktion SQL_Comp12() liefert eine Auflistung der verknüpften Felder der ersten Tabelle und der verglichenen Felder beider Tabellen. Sie wird in der SELECT-Anweisung der Abfrage Unterschiedliche Werte eingesetzt.
Function SQL_Comp12()
...
For i = 0 To UBound(arrJoin1)
s = s & "T1.[" & Trim$(arrJoin1(i)) & "],"
Next i
For i = 0 To UBound(arrComp1)
s = s & "T1.[" & Trim$(arrComp1(i)) & "],"
& "T2.[" & Trim$(arrComp2(i)) & "],"
Next i
SQL_Comp12 = Left$(s, Len(s) - 1)
Die Funktion SQL_FieldEq() liefert den Ausdruck für das Finden der gleichen Inhalte der verglichenen Felder beider Tabellen. Die Vergleichsoperationen werden in diesem Fall mit dem logischen Operator AND verbunden. Die Funktion wird im WHERE-Ausdruck der Abfrage Gleiche Werte eingesetzt.
Wenn beide verglichenen Felder NULL enthalten, werden sie auch als gleiche Werte behandelt.
Public Function SQL_FieldEq() As String
...
For i = 0 To UBound(arrComp1)
s = s & "((T1.[" & Trim$(arrComp1(i))
& "]=" & "T2.[" & Trim$(arrComp2(i))
& "]) OR "
s = s & "(IsNull(T1.["
& Trim$(arrComp1(i)) & "]) AND "
s = s & "IsNull(T2.["
& Trim$(arrComp2(i)) & "]))) AND "
Next i
SQL_FieldEq = Left$(s, Len(s) - 5)
Die Funktion SQL_FieldDiff() liefert den Ausdruck für das Finden der Unterschiede der verglichenen Felder beider Tabellen. Die Vergleichsoperationen werden in diesem Fall mit dem logischen Operator OR verbunden. Die Funktion wird im WHERE-Ausdruck der Abfrage Unterschiedliche Werte eingesetzt.
Wenn nur eines der Felder NULL enthält, werden sie auch als nicht gleiche Werte behandelt.
Function SQL_FieldDiff() As String
...
For i = 0 To UBound(arrComp1)
s = s & "((T1.[" & Trim$(arrComp1(i))
& "]<>" & "T2.[" & Trim$(arrComp2(i))
& "]) OR "
s = s & "(IsNull(T1.[" & Trim$(arrComp1(i))
& "])<>"
& "IsNull(T2.[" & Trim$(arrComp2(i))
& "]))) OR "
Next i
SQL_FieldDiff = Left$(s, Len(s) - 4)
Die Abfragen Tabelle1 und Tabelle 2 zeigen alle ausgewählten Felder (zuerst die Schlüsselfelder) einer Tabelle an. Die Ereignis-Prozedur der Schatfläche cmdTab1 hat die einfachste mögliche Form.
Sub cmdTab1_Click()
QueryDefOpen "Tabelle 1",
"SELECT " & SQL_JoinComp(1) & " FROM T1"
Der SQL-Ausdruck für diese und weitere Abfragen besteht aus den Rückgabewerten mehrerer SQL-Teilfunktionen und wird zuerste in der Variablen s zusammengesetzt, bevor er an die Funktion QueryDefOpen() übergeben wird.
Um die fehlenden Datensätze (Schlüsselwerte) zu finden, wird in der WHERE Anweisung der Wert des ersten verknüpften Feldes der anderen Tabelle auf den Wert NULL überprüft.
Sub cmdTab1more_Click()
...
s = "SELECT DISTINCT " & SQL_JoinComp(1)
& " FROM T1 LEFT JOIN T2"
& " ON " & SQL_Joins()
& " WHERE T2.[" & arrJoin2(0) & "] IS NULL"
QueryDefOpen "Fehlende in der Tabelle 2", s
Bei einem positiven Ergebnis dieses Vergleichs sind sowohl alle verknüpften als auch alle verglichenen Felder beider Tabellen gleich. Aus diesem Grund werden nur die Felder der ersten Tabelle mit der Teilfunktion SQL_JoinComp(1) angezeigt.
Den Verknüpfungsausdruck wird von der Funktion SQL_Joins() und der Filterausdruck von der Funktion SQL_FieldEq() geliefert.
Private Sub cmdFeldEq_Click()
...
s = "SELECT DISTINCT "
& SQL_JoinComp(1)
& " FROM T1 INNER JOIN T2"
& " ON " & SQL_Joins()
& " WHERE " & SQL_FieldEq()
QueryDefOpen "Gleiche Werte", s
In dieser Abfrage werden die verknüpften Felder der ersten Tabelle und die verglichenen Felder beider Tabellen mit der Funktin SQL_Comp12() angezeigt.
Den Verknüpfungsausdruck bleibt gleich wie in der Abfrage Gleiche Werte und der Filterausdruck wird von der Funktion SQL_FieldDiff() geliefert.
Private Sub cmdFeldDiff_Click()
...
s = "SELECT DISTINCT "
& SQL_Comp12()
& " FROM T1 INNER JOIN T2"
& " ON " & SQL_Joins()
& " WHERE " & SQL_FieldDiff()
QueryDefOpen "Unterschiedliche Werte", s
Die mit dem vorgestellten Tool dynamisch erstellten Abfragen bleiben in der Datenbank CompTab.mdb solange gespeichert, bis Sie einen neuen Vergleich durchführen.
Sie stehen Ihnen wie alle anderen Abfragen im Datenbankfenster zur Verfügung. Sie können sie unter einem anderen Namen speichern, in andere Datenbanken exportieren, verändern und beliebig weiter verwenden.