Zwei oder mehr Access-Datenbanken(.mdb) zusammenführen

  • VB.NET
  • .NET (FX) 4.5–4.8

Es gibt 11 Antworten in diesem Thema. Der letzte Beitrag () ist von mmgg.

    Zwei oder mehr Access-Datenbanken(.mdb) zusammenführen

    Hi,

    ich komme nicht mehr weiter.

    Ich muss (mindestens) zwei gleich aufgebaute Datenbanken (also die einzelnen darin befindlichen Tabellen) miteinander verbinden. Dabei müssen die Werte in der Spalte mit dem Titel Namen "ID" der "Slave"-Tabelle immer um den maximalen Wert der Spalte "ID" der "Master"-Tabelle erhöht werden. Das Gleiche auch bei "ImageFile"

    Aufbau der Datenbanken:
    tbl_Images: ID, Number, ImageFile
    tbl_Search: Field1, Field2, Field3 Pages, ID, Note
    tbl_Übersicht: ID, Field1, Field2, Field3, Pages, Note

    Images: ID, Number, ImageFile
    Search: Field1, Field2, Field3 Pages, ID, Note
    Übersicht: ID, Field1, Field2, Field3, Pages, Note

    Images:
    IDNumberImageFile
    111
    122
    213
    224
    235

    Search:
    Field1Field2Field3PagesIDNote
    ArnoNym123421
    MaxMustermann133732

    Übersicht:
    IDField1Field2Field3PagesNote
    1ArnoNym12342
    2MaxMustermann13373

    Wenn ich zwei mal die gleiche Datenbank auswähle, sollte das dann so aussehen:

    Images:
    ID
    NumberImageFile
    111
    122
    213
    224
    235
    316
    327
    418
    429
    4310

    Search:
    Field1
    Field2
    Field3
    Pages
    ID
    Note
    1ArnoNym21
    2MaxMustermann32
    3ArnoNym23
    4MaxMustermann34

    Übersicht:
    ID
    Field1
    Field2
    Field3
    Pages
    Note
    1ArnoNym12342
    2MaxMustermann13373
    3ArnoNym12342
    4MaxMustermann13373

    ID 1 & 2 <= DB1
    ID 3 & 4 <= DB2


    Mein Versuch war bisher durch den SQL bzw. OleDB-Befehl

    VB.NET-Quellcode

    1. "SELECT MAX(ID) FROM [Search];"

    den höchsten ID-Wert der Mastertabellen herauszubekommen (hier in dem Beispiel wäre das die 2) und dann anschließend beide Tabellen durch den SQL/OleDB-Befehl

    VB.NET-Quellcode

    1. "SELECT * from [Übersicht] " & _
    2. "UNION ALL " &
    3. "SELECT ID+" & maxID & ", Field1, Field2, Field3, Pages, Note from [Übersicht] IN '" & dbPath2 & "';"

    zu verbinden.
    Problem ist jetzt, dass die eine Tabelle zwar richtig dargestellt wird, ich das aber bei allen drei Tabellen (eigentlich sinds 7, bei dem Rest braucht sich aber nichts zu verändern) machen müsste und das dann auch irgendwie abspeichern muss.

    Gibt es irgendeine leichtere Variante die Datenbanken miteinander zu verbinden? Oder einen SQL/OleDB-Befehl der alles zusammenfasst?

    Kennt ihr vielleicht wenigstens einen Befehl, mit dem ich die Spalten-Titel Spalten-Namen irgendwie abrufen kann, damit ich eine Funktion basteln kann, in die ich die einzelnen Tabellen einfach "reinwerfen" kann?
    Ich finde nichts dazu im Internet - vielleicht suche ich auch falsch...

    Wäre lieb, wenn mir jemand helfen könnte. Vielen Dank, dass du bis hier her gelesen hast

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „Rasalas“ ()

    Hi,
    du hast dir bei deiner beschr. sicher mühe gegeben, trotzdem sind da ein paar sachen ....

    Du schreibst hier:
    "SELECT MAX(ID) FROM [Search];"
    Ich nehm mal an, es ist tbl_search, oder? Wenn sie es ist, wieso ist dann die 2 der höchste wert.

    Dann schreibst du von datenbanken, deine wenigen codezeilen sehen aber nicht so aus, als würden die tables in versch datenbanken liegen?

    bei "Spalten-Titel" geh ich jetzt mal davon aus, dass Splaten-Namen gemeint sind.
    Mit einem Datareader kannst du das Schema von Tabellen abrufen, damit dann auch die Spalten-Namen.

    Diese Function gibt dir eine Tabelle mit einem best. schema. Guck dir aber nochmal "CommandBehavior.KeyInfo" an, neben keyinfo gibt es auch Schemaonly.
    Ich stell das mal dazu, auch wenn ich nicht seh, wie dir das helfen kann.

    Quellcode

    1. Private Function DrExecuteReaderKeyInfo(ByVal myCnn As OleDbConnection, _
    2. ByVal strSQL As String) As DataTable
    3. Dim dt As DataTable
    4. Dim myCmd As New OleDbCommand
    5. Dim dr As OleDbDataReader = Nothing
    6. myCmd.CommandText = strSQL
    7. myCmd.Connection = myCnn
    8. dr = myCmd.ExecuteReader(CommandBehavior.KeyInfo)
    9. dt = dr.GetSchemaTable
    10. Return dt
    11. End Function
    JonDonym
    Eine Anonymisierung-Tool, das nicht nur deine IP verdeckt, sondern deine History, BrowserTyp, Windows-Version etc.
    Das Tool hat ca. 5 FreeKaskaden und ca. 10 Premium. Minimum 5 EUR für ein Volumen von 650MB.
    Überleg dir was du brauchst, und schreib dir ein Modul, was das kann.

    Also um eine Tabelle von der einen DB in die annere zu kopieren braucht man
    1. sourceConnection
    2. destConnection
    3. Tablename
    4. alle Columnames dieser Table
    5. die Columnames der IDs, die hochzuzählen sind
    ja, und dann musste klugen Code schreiben, der geeignetes Sql konstruiert, und damit ein paar DbCommands bauen, unter Verwendung von DbParametern.
    Aber mach erstmal ein Modul fertig, wo du von aussen überhaupt die genannte Eckdaten festlegen kannst.

    Poste das Modul, dann sieht man weiter.

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „ErfinderDesRades“ ()

    mmgg schrieb:


    Du schreibst hier:
    "SELECT MAX(ID) FROM [Search];"
    Ich nehm mal an, es ist tbl_search, oder? Wenn sie es ist, wieso ist dann die 2 der höchste wert.

    Nein, ich meine Search. Tut mir leid - habe ich oben korrigiert. Die Tabelle in der Datenbank heißt "Search" (wie auch oben in den Tabellen "visualisiert".)

    mmgg schrieb:


    Dann schreibst du von datenbanken, deine wenigen codezeilen sehen aber nicht so aus, als würden die tables in versch datenbanken liegen?


    Hier mein, logischerweise unfertiger, Ansatz:

    VB.NET-Quellcode

    1. Private Sub connectDBs()
    2. dbPath1 = "C:\temp\DB1\scfdata.mdb"
    3. dbPath2 = "C:\temp\DB2\scfdata.mdb"
    4. Dim selectCommand As String = "SELECT * from [Übersicht] " & _
    5. "UNION ALL " &
    6. "SELECT ID+" & maxID & ", Field1, Field2, Field3, Pages, Note from [Übersicht] IN '" & dbPath2 & "';"
    7. connectionString = _
    8. "Provider=Microsoft.Jet.OLEDB.4.0;" &
    9. "Data Source=" & dbPath1 & ";"
    10. Dim bs As New BindingSource
    11. Dim ds As DataSet
    12. Dim dt As DataTable
    13. Dim da As OleDbDataAdapter
    14. Dim cb As OleDbCommandBuilder
    15. Try
    16. ds = New DataSet()
    17. da = New OleDbDataAdapter(selectCommand, connectionString)
    18. cb = New OleDbCommandBuilder(da)
    19. da.Fill(ds, "Übersicht")
    20. dt = ds.Tables("Übersicht")
    21. If bs.DataSource IsNot Nothing Then
    22. bs.DataSource = Nothing
    23. End If
    24. bs.DataSource = dt
    25. dgvTest.DataSource = bs
    26. Catch ex As OleDbException
    27. MessageBox.Show(ex.Message)
    28. End Try
    29. End Sub

    mmgg schrieb:


    bei "Spalten-Titel" geh ich jetzt mal davon aus, dass Splaten-Namen gemeint sind.
    Mit einem Datareader kannst du das Schema von Tabellen abrufen, damit dann auch die Spalten-Namen.

    Richtig - habe ich oben korrigiert.
    Muss ich mal ausprobieren - vielen Dank.

    Ich überlegte die Spalten-Namen in eine List<of T> zu schreiben und den SQL-/OleDB-String dann basierend darauf zu erstellen. Die Function würde mir dann den Wert für "selectCommand" zurückgeben (genauso für die anderen Tabellen).

    So:
    (die Function "getConnectCommand(x As List(Of String))"müsste ich dann noch basteln)

    VB.NET-Quellcode

    1. Dim selectCommand As String = Wrkbnch.getConnectCommand(lstColumnNames)

    Dieser Beitrag wurde bereits 2 mal editiert, zuletzt von „Rasalas“ ()

    ähm - sagst du Bescheid, wenn du aufhörst, mich zu ignorieren, und anfängst wahrzunehmen, was ich versuche mitzuteilen?
    weil ich teile dir ja 5 Dinge mit, die überhaupt Vorraussetzung sind, um eine Tabelle zu transferieren.
    Ignorierst du mich, weil du nicht verstehst, warum das die Vorraussetzungen sind?
    Dann wäre besser, du fragst nach, denn durch Ignorieren hören diese Vorraussetzungen auch nicht damit auf, Vorraussetzung zu sein.
    Oder bist du anderer Meinung, also meinst, nur mit einem Teil des genannten auszukommen, etwa nur mit 2 Dateinamen und einer List(Of T)?
    Sorry,
    der Code oben ist was ich schon hatte, bevor ihr netterweise geantwortet hattet.

    Ja - ich habe vermutlich nicht richtig verstanden was du meinst, bzw. dachte Teile davon wären schon in meinem Code enthalten. Ich hatte bisher keine Zeit die oben genannten Dinge zu googeln.

    zu 1+2. Ich dachte du meintest einfach die Dateipfade.
    zu 3. Habe ich.
    zu 4. Danach hatte ich im ersten Posting gefragt.
    zu 5. Joa habe ich.

    Nein, ich bin nicht der Meinung, dass der oben genannte Code ausreicht.

    Sorry nochmal - war etwas missverständlich. Und auch dir vielen Dank.
    @Erfinder
    User sind gehalten dir zu antworten, wenn du antwortest?
    Die dicken 5 Voraussetzungen sind das was er nicht wusste?

    @Rasalas
    Ok, die Tabelle ist Search. Nur der höchste wert ist nicht 2, es ist 4? Sorry, will nicht spitzfindisch sein, nur um eben dem nah zukommen was du letztlich machne willst ....

    Was ich jetzt schreib basiert mehr oder weniger auf interpretation.
    Da sind also 3 Tabellen die du zusammen führen willst, aber allein per union gehts nicht? Weil evntl die Datentypen nicht immer gleich sind oder die Anzahl der Fields ungleich?

    Ausserdem willst du nicht alle Daten zusammenführen sondern nur ein Teil?

    Die DataTable, die du von der function bekommst(aus dem beispiel von mir oben) die kannst du auslesen, du hast in der tabelle zu jeder Spalte auch immer den Tabellenamen.

    Einen String daraus zusammensetzten, wird dir nicht so schwer fallen.
    JonDonym
    Eine Anonymisierung-Tool, das nicht nur deine IP verdeckt, sondern deine History, BrowserTyp, Windows-Version etc.
    Das Tool hat ca. 5 FreeKaskaden und ca. 10 Premium. Minimum 5 EUR für ein Volumen von 650MB.

    mmgg schrieb:

    @Erfinder
    User sind gehalten dir zu antworten, wenn du antwortest?
    Die dicken 5 Voraussetzungen sind das was er nicht wusste?
    Naja, das wäre jdfs eine zielgerichtete Vorgehensweise.
    Wenn er antworten und das Modul posten würde - nach eigener Aussage hat er ja eiglich alles bereits beisammen - dann könnte man recht schnell den fehlenden Code ergänzen.

    Die Idee ist, erstmal eine Rahmen-Architektur herzustellen - gewissermassen mit Leerstellen.
    Hierfür ist überhaupt kein besonderes Wissen nötig - es sind ja nur ein paar Strings.

    Ich nehme auch an, die 5 Vorraussetzungen sind ihm selbstverständlich. Nur den Schritt, aus diesen Selbstverständlichkeiten nu ein Modul zu coden - ja, müsste er halt mal machen.
    Dass man Variablen hat mit Namen, mit denen man was anstellen kann.

    ErfinderDesRades schrieb:


    Übrigens bei Google wirst du das Modul nicht finden - du musst es selbst programmieren.
    Oder wonach wolltest du googeln?

    Mir ist bekannt, dass ich das "Modul" nicht bei Google finden werde.
    Ich habe VB.NET durch einen Sprung ins kalte Wasser gelernt. Fachbegriffe sind mir nicht so geläufig. Du verwendest relativ viele davon.
    Ist der oben geschiebene Code nicht auch ein "Modul"? Da stehen m.E. alle Daten drin. Der Code funktioniert auch für die Tabelle "Übersicht" die ich brauche. Ich poste aber in kürze mal was, das etwas besser ausgearbeitet ist...

    mmgg schrieb:



    Ok, die Tabelle ist Search. Nur der höchste wert ist nicht 2, es ist 4? Sorry, will nicht spitzfindisch sein, nur um eben dem nah zukommen was du letztlich machne willst ....
    [...]
    Ausserdem willst du nicht alle Daten zusammenführen sondern nur ein Teil?


    :D
    Also:

    Nehmen wir an, dass ich eine Datenbank besitze, in der ich immer wieder irgendwas finden muss. Hin und wieder bekomme ich eine Datenbank zugeschickt, die neue Datensätze enthält.
    Jetzt möchte ich die alte Datenbank mit der neuen Datenbank verbinden, damit ich nicht immer zwischen den Dankenbanken wechseln muss (z.B. falls ich etwas in den Datenbanken suchen muss.).

    Die Datenbanken sehen, wenn man grob drauf schaut, so aus(hab ich oben zwar schon versucht zu visualisieren, aber vielleicht versteht man es besser, wenn es ein Stück kleiner ist - und ganz ohne Daten):

    Datenbank.mdb
    ----Images
    --------ID <--hier ist das Maximum 2 --> maxID = 2
    --------Number
    --------ImageFile
    ----Search
    --------Field1
    --------Field2
    --------Field3
    --------Pages
    --------ID <--hier ist das Maximum 2
    --------Note
    ----Übersicht
    --------ID <--hier ist das Maximum 2
    --------Field1
    --------Field2
    --------Field3
    --------Pages
    --------Note

    Oben hatte ich 2x die gleiche Datenbank genommen und sie zusammengeführt(damit man sieht, was wo hin gekommen ist).
    Die unteren drei Tabellen (von oben) sind also das Ergebnis folgender "Operationen":

    bei "+" wird jeder Wert in der jeweiligen Zeile einzeln behandelt.
    bei "&" werden alle Datensätze hinter-/untereinander geschrieben.

    Datenbank.mdb + Datenbank.mdb
    ----Images
    --------ID & (ID + maxID))
    --------Number & Number
    --------ImageFile & (ImageFile + maxID)
    ----Search
    --------Field1 & Field1
    --------Field2 & Field2
    --------Field3 & Field3
    --------Pages & Pages
    --------ID & (ID + maxID)
    --------Note & Note
    ----Übersicht
    --------ID & (ID + maxID)
    --------Field1 & Field1
    --------Field2 & Field2
    --------Field3 & Field3
    --------Pages & Pages
    --------Note & Note

    Falls das nicht verständlich genug ist - oben steht ja der SQL-Befehl, der die Tabelle "Übersicht" behandelt. Vielleicht versteht man es dadurch.

    Bei "Datenbank.mdb + Datenbank.mdb" ist dann die maximale ID 4(das ist wohl die Zahl, die du gesehen hast), weil 2(dbAlt)+2(dbNeu)=4(dbZusammen)

    Rasalas schrieb:

    Ist der oben geschiebene Code nicht auch ein "Modul"?
    Nein, das ist eine Sub.
    Module ist ein vb.net-Schlüsselwort - sowas ähnliches wie eine Klasse, aber anners.
    Und in der Sub finde ich nur Variablen für die beiden Db-Pfade.
    Für die Tabellen-namen gibts in deiner Sub keine Variablen, und für die Namen der Id-Schlüsselfelder auch nicht. (und deswegen ist die Sub auch nicht variabel).

    Und natürlich langt eine Sub hier nicht hin, es muss ein Modul sein.
    Denn die DB-Pfade werden sich ja nicht verändern pro Kopier-Vorgang, wohl aber die Tabellennamen - genauer: der Tabellenname, denn die Tabellen heißen ja in beiden Dbs gleich.

    Interessant, dass du "Fachbegriffe" ansprichst - das ist tatsächlich ein wichtiges Thema - hab ich sogar ein Tut zu verzapft: Grundlagen: Fachbegriffe
    Leider ist "Modul" dort nicht enthalten, das kannste vlt hier recherchieren.
    "Falls das nicht verständlich genug ist - oben steht ja der SQL-Befehl, der die Tabelle "Übersicht" behandelt. Vielleicht versteht man es dadurch."

    Nein, versteh ich nicht.

    2+2 = 4, glaub ich nicht
    JonDonym
    Eine Anonymisierung-Tool, das nicht nur deine IP verdeckt, sondern deine History, BrowserTyp, Windows-Version etc.
    Das Tool hat ca. 5 FreeKaskaden und ca. 10 Premium. Minimum 5 EUR für ein Volumen von 650MB.