kommentiert. Falls Fragen sind -> immer her damit.
(benötigt PB4.3 und die ExDataBase-Lib von Michael)
Code: Alles auswählen
EnableExplicit
UseODBCDatabase()
Procedure CompareDatabases(Database1.s, Database2.s)
Protected DBDSN1.s, DBDSN2.s
Protected DB1, DB2
Protected ColCounter
Protected Fieldnames.s, Query.s
Structure s_Info
Name.s
IsIn.l
EndStructure
NewList Tableinfo1.s_Info()
NewList Tableinfo2.s_Info()
NewList ColumnInfo1.s_Info()
NewList ColumnInfo2.s_Info()
NewList Record1.s()
NewList Record2.s()
; DB1 -> Tabellennamen auslesen
DBDSN1 = AddDSN(Database1)
If ExamineTables(DBDSN1)
While NextTable()
If GetTableType() = "TABLE"
AddElement(Tableinfo1())
Tableinfo1()\Name = GetTableName()
EndIf
Wend
EndIf
; DB2 -> Tabellennamen auslesen
DBDSN2 = AddDSN(Database2)
If ExamineTables(DBDSN2)
While NextTable()
If GetTableType() = "TABLE"
AddElement(Tableinfo2())
Tableinfo2()\Name = GetTableName()
EndIf
Wend
EndIf
; Vergleich Tabellen DB1 <-> DB2
ForEach Tableinfo1()
ForEach Tableinfo2()
If Tableinfo1()\Name = Tableinfo2()\Name
Tableinfo1()\IsIn=#True
Tableinfo2()\IsIn=#True
Break
EndIf
Next
Next
; Ausgabe: welche Tabellen sind nicht vorhanden
ForEach Tableinfo1()
If Not Tableinfo1()\IsIn
Debug "Tabelle in DB1, aber nicht in DB2: " + Tableinfo1()\Name
DeleteElement(Tableinfo1()) ; nicht vorhandene Tabellen werden entfernt
EndIf
Next
ForEach Tableinfo2()
If Not Tableinfo2()\IsIn
Debug "Tabelle in DB2, aber nicht in DB1: " + Tableinfo2()\Name
DeleteElement(Tableinfo2()) ; nicht vorhandene Tabellen werden entfernt
EndIf
Next
; Spaltennamen vergleichen
; Dateninhalte vergleichen
DB1 = OpenDatabase(#PB_Any, DBDSN1, "", "", #PB_Database_ODBC)
If DB1
DB2 = OpenDatabase(#PB_Any, DBDSN2, "", "", #PB_Database_ODBC)
If DB2
ForEach Tableinfo1() ; Tableinfo1 und Tableinfo2 sind nun synchron
ClearList(ColumnInfo1())
ClearList(ColumnInfo2())
; Spaltennamen Tabelle X in DB 1 auslesen
If DatabaseQuery(DB1, "Select * From [" + Tableinfo1()\Name + "] Where 1=2")
NextDatabaseRow(DB1)
For ColCounter = 1 To DatabaseColumns(DB1)
AddElement(ColumnInfo1())
ColumnInfo1()\Name = DatabaseColumnName(DB1, ColCounter - 1)
Next
FinishDatabaseQuery(DB1)
EndIf
; Spaltennamen Tabelle X in DB 2 auslesen
If DatabaseQuery(DB2, "Select * From [" + Tableinfo1()\Name + "] Where 1=2")
NextDatabaseRow(DB2)
For ColCounter = 1 To DatabaseColumns(DB2)
AddElement(ColumnInfo2())
ColumnInfo2()\Name = DatabaseColumnName(DB2, ColCounter - 1)
Next
FinishDatabaseQuery(DB2)
EndIf
; Vergleich Spalten Tabelle X in DB1 <-> Tabelle X in DB2
ForEach ColumnInfo1()
ForEach ColumnInfo2()
If ColumnInfo1()\Name = ColumnInfo2()\Name
ColumnInfo1()\IsIn=#True
ColumnInfo2()\IsIn=#True
Break
EndIf
Next
Next
; Ausgabe: welche Spalten sind nicht vorhanden
ForEach ColumnInfo1()
If Not ColumnInfo1()\IsIn
Debug "Spalte in Tabelle " + Tableinfo1()\Name + " in DB1, aber nicht in DB2: " + ColumnInfo1()\Name
DeleteElement(ColumnInfo1()) ; nicht vorhandene Spalten werden entfernt
EndIf
Next
ForEach ColumnInfo2()
If Not ColumnInfo2()\IsIn
Debug "Spalte in Tabelle " + Tableinfo1()\Name + " in DB2, aber nicht in DB1: " + ColumnInfo2()\Name
DeleteElement(ColumnInfo2()) ; nicht vorhandene Spalten werden entfernt
EndIf
Next
; Nun Zeileninhalte miteinander vergleichen
; Query zusammenbasteln
Fieldnames = ""
ForEach ColumnInfo1() ; ColumnInfo1 und ColumnInfo2 sind nun synchron
Fieldnames + "[" + ColumnInfo1()\Name + "]"
If ListIndex(ColumnInfo1()) < ListSize(ColumnInfo1()) - 1
Fieldnames + ", "
EndIf
Next
Query = "Select " + Fieldnames + " From " + Tableinfo1()\Name + " Order By " + Fieldnames
ClearList(Record1())
ClearList(Record2())
If DatabaseQuery(DB1, Query)
While NextDatabaseRow(DB1)
AddElement(Record1())
ForEach ColumnInfo1() ; ColumnInfo1 und ColumnInfo2 sind nun synchron
Record1() + GetDatabaseString(DB1, ListIndex(ColumnInfo1()))
If ListIndex(ColumnInfo1()) < ListSize(ColumnInfo1()) - 1
Record1() + Chr(10)
EndIf
Next
Wend
FinishDatabaseQuery(DB1)
EndIf
If DatabaseQuery(DB2, Query)
While NextDatabaseRow(DB2)
AddElement(Record2())
ForEach ColumnInfo1() ; ColumnInfo1 und ColumnInfo2 sind nun synchron
Record2() + GetDatabaseString(DB2, ListIndex(ColumnInfo1()))
If ListIndex(ColumnInfo1()) < ListSize(ColumnInfo1()) - 1
Record2() + Chr(10)
EndIf
Next
Wend
FinishDatabaseQuery(DB2)
EndIf
If ListSize(Record1()) <> ListSize(Record2())
; todo
; anzahl datensätze unterschiedlich
; vergleich theoretisch möglich
Else
ForEach Record1()
SelectElement(Record2(), ListIndex(Record1()))
If Record1() <> Record2()
ForEach ColumnInfo1()
Protected Field1.s = StringField(Record1(), ListIndex(ColumnInfo1()) + 1, Chr(10))
Protected Field2.s = StringField(Record2(), ListIndex(ColumnInfo1()) + 1, Chr(10))
If Field1 <> Field2
Debug "Tabelle: " + Tableinfo1()\Name + " / Spalte: " + ColumnInfo1()\Name
Debug Field1 + " / " + Field2
Debug ""
EndIf
Next ; ForEach ColumnInfo1()
EndIf ; If Record1() <> Record2()
Next ; ForEach Record1()
EndIf
Next
CloseDatabase(DB2)
Else
Debug "Konnte " + Database1 + " nicht öffnen"
EndIf
CloseDatabase(DB1)
Else
Debug "Konnte " + Database2 + " nicht öffnen"
EndIf
; Schlussendlich die DSN wieder entfernen
RemoveDSN(Database2)
RemoveDSN(Database1)
EndProcedure
CompareDatabases("D:\db1.mdb", "D:\db2.mdb")
// Edit: Code korrigiert. Verschobene Spalten sollten nun nicht mehr vorkommen.