Struktur einer *.mdb Datenbank kopieren (Leere DB erzeugen)

  • VB.NET

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

    Struktur einer *.mdb Datenbank kopieren (Leere DB erzeugen)

    Schön war's ganz früher mit "copy stru" und fertig!
    Mein VB6-Proggis werden von den Schergen des Mr. Gates immer weiter abgeschaltet; hoffentlich hat VB2010 eine Zukunft...
    Hier versuche ich, aus uralten FoxPro-Tabellen eine mdb zu schmieden, um wenigstens den datenpool ins neue Zeitalter zu retten...

    Scheinbar klappt mein (laienhafter) Code; aber die scheinbar leere DB hat physikalisch immer noch die gleiche Größe auf der Festplatte wie als ich noch tausende Datensätze 'drin hatte. Kann mir da einer auf die Sprünge helfen?
    Vielen Dank!

    VB.NET-Quellcode

    1. Imports System.Data.OleDb
    2. Public Class frmMain
    3. Dim zielcon As New OleDbConnection
    4. Dim zielcmd As New OleDbCommand
    5. Dim mySQL As String
    6. Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
    7. Dim QAnzahl As Integer, ZAnzahl As Integer
    8. ListBox1.Items.Clear()
    9. zielcon.ConnectionString = "Provider=Microsoft.Jet.OLEDB.4.0; Data Source=E:\uLis Zeughaus\Verwaltung.mdb"
    10. zielcmd.Connection = zielcon
    11. zielcon.Open()
    12. zielcmd.CommandText = "SELECT COUNT (Knr) FROM Termine"
    13. QAnzahl = CInt(zielcmd.ExecuteScalar())
    14. zielcmd.CommandText = "DELETE * FROM Termine WHERE Knr > 0 "
    15. ZAnzahl = CInt(zielcmd.ExecuteScalar())
    16. ListBox1.Items.Add((QAnzahl - ZAnzahl).ToString("00000") & " Termine entfernt")
    17. zielcmd.CommandText = "SELECT COUNT (AnschriftZ1) FROM Anschriften"
    18. QAnzahl = CInt(zielcmd.ExecuteScalar())
    19. zielcmd.CommandText = "DELETE * FROM Anschriften WHERE AnschriftZ1 <> ''"
    20. ZAnzahl = CInt(zielcmd.ExecuteScalar())
    21. ListBox1.Items.Add((QAnzahl - ZAnzahl).ToString("00000") & " Fremdadressen entfernt")
    22. zielcmd.CommandText = "SELECT COUNT (BLZ) FROM Banken"
    23. QAnzahl = CInt(zielcmd.ExecuteScalar())
    24. zielcmd.CommandText = "DELETE * FROM Banken WHERE BLZ IS NOT NULL"
    25. ZAnzahl = CInt(zielcmd.ExecuteScalar())
    26. ListBox1.Items.Add((QAnzahl - ZAnzahl).ToString("00000") & " Banken entfernt")
    27. zielcmd.CommandText = "SELECT COUNT (Knr) FROM Kunden"
    28. QAnzahl = CInt(zielcmd.ExecuteScalar())
    29. zielcmd.CommandText = "DELETE * FROM Kunden WHERE Knr IS NOT NULL"
    30. ZAnzahl = CInt(zielcmd.ExecuteScalar())
    31. ListBox1.Items.Add((QAnzahl - ZAnzahl).ToString("00000") & " Kunden entfernt")
    32. zielcmd.CommandText = "SELECT COUNT (Ort) FROM Postleitzahlen"
    33. QAnzahl = CInt(zielcmd.ExecuteScalar())
    34. zielcmd.CommandText = "DELETE * FROM Postleitzahlen WHERE Ort IS NOT NULL"
    35. ZAnzahl = CInt(zielcmd.ExecuteScalar())
    36. ListBox1.Items.Add((QAnzahl - ZAnzahl).ToString("00000") & " Sätze Postleitzahlen entfernt")
    37. zielcmd.CommandText = "SELECT COUNT (Knr) FROM Verträge"
    38. QAnzahl = CInt(zielcmd.ExecuteScalar())
    39. zielcmd.CommandText = "DELETE * FROM Verträge WHERE Knr IS NOT NULL"
    40. ZAnzahl = CInt(zielcmd.ExecuteScalar())
    41. ListBox1.Items.Add((QAnzahl - ZAnzahl).ToString("00000") & " Datensätze Verträge entfernt")
    42. zielcmd.CommandText = "COMMIT"
    43. zielcon.Close()
    44. End Sub
    45. End Class


    *Topic verschoben*

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „Marcus Gräfe“ ()

    Ich kenn mich nicht wirklich aus, aber...

    VB.NET-Quellcode

    1. zielcmd.CommandText = "COMMIT"


    fehlt da nicht noch sowas wie

    VB.NET-Quellcode

    1. zielcmd.Execute
    2. ' oder
    3. zielcmd.ExecuteScalar


    oder ähnlich?

    Ansonsten via Datatables... hast du auch tolle commands. Du arbeitest mit der table, sagst am Ende nur DataAdapter.Update(dataTable) und fertsch...

    JoyMan schrieb:

    Scheinbar klappt mein (laienhafter) Code; aber die scheinbar leere DB hat physikalisch immer noch die gleiche Größe auf der Festplatte wie als ich noch tausende Datensätze 'drin hatte. Kann mir da einer auf die Sprünge helfen?
    Access kennt keine Gnade: Die Dateien haben immer eine ziemlich happige Mindestgröße.
    am besten du steigst auf SqlServer um, da hast du dann gleich die 4-fache Mindestgröße.

    (warn Witz ;)) Begründet wird dieses Mindestgrößen-Theater damit, dass eine DB leeren Platz vorhalten muß, damit sie sich nicht zu oft restrukturieren muß.

    Da wundert man sich dann über SQLite, dessen Mindestgröße unter 10KB auskommt. Oder SqlCe, das braucht "nur" ca. 120KB.

    Also im Ernst: Für ein Einzelplatz-System ist SqlCe die beste Wahl, weil bei SqLite konnten die Gates-Schergen bisher erfolgreich verhindern, dasses auch von VB2010 unterstützt wird :cursing: .


    Beachte: Das erklärt, warum deine Ergebnis-Dateien auf jeden Fall pervers fett sind, aber das bedeutet noch nicht, dass dein Code wirklich fehlerfrei ist.

    meine alten grauen Haare sind altersbedingt - die neuen nicht!

    ErfinderDesRades schrieb:

    Beachte: Das erklärt, warum deine Ergebnis-Dateien auf jeden Fall pervers fett sind, aber das bedeutet noch nicht, dass dein Code wirklich fehlerfrei ist.
    Wie pervers sind knappe 12MB für eine leere DB?
    Aber ist nicht das Thema; den Platz sollte jeder haben ... Fehlerfrei?! Ich dachte da an Antworten wie: "So geht das garnicht, sondern.." oder "Naja, fürn Deppen nich schlecht"

    Kagurame schrieb:

    zielcmd.Execute
    ' oder
    zielcmd.ExecuteScala oder ähnlich?
    ... macht keinen Unterschied, nimmter hin und schweigt. Über DataTables würd' ich mich gern aufklären lassen!

    @ FlashTek
    mit meinen bescheidenen Mitteln kann ich keine Einträge mehr finden. Ich wäre mir wirklich gern sicher, das da nicht's mehr drinsteht, bevor ich's weitergebe.
    DataTable-Class

    Ansonsten mal ein wenig Beispiel-Code (welcher bei mir auf eine SQL-CE-Klasse zurecht geschnitten ist, die selben Klassen gibt es auch für normale SQL-DB´s)

    Code-Snippets

    VB.NET-Quellcode

    1. Dim changedRows = From row As DataRow In dtChanges.AsEnumerable Where row.RowState = DataRowState.Added

    (Herausfinden, welche Rows neu sind, sprich neue Datensätze)

    Spoiler anzeigen

    VB.NET-Quellcode

    1. Private Function UpdateSql(dt As DataTable, getId As Boolean) As Integer
    2. Dim tableName As String = Quote(dt.TableName)
    3. Dim sql As String = String.Format("SELECT * FROM {0}", tableName)
    4. Dim identity As Integer = -1
    5. 'Neue Connection erstellen. "Using" stellt sicher, dass "Dispose" gerufen wird.
    6. Using cnn As New SqlCeConnection(("lalala"))
    7. With cnn
    8. .Open()
    9. DataBaseLogger.GetInstance.Log(NLog.LogLevel.Trace, "connecting to database")
    10. 'Command erzeugen; Connection mit geben
    11. Using cmd As New SqlCeCommand(sql, cnn)
    12. DataBaseLogger.GetInstance.Log(NLog.LogLevel.Trace, sql)
    13. 'DataAdapter erzeugen; (Select-)Command mitgeben
    14. Using da As New SqlCeDataAdapter(cmd)
    15. 'CommandBuilder erzeugen; DataAdapter mitgeben
    16. Using cb As New SqlCeCommandBuilder(da)
    17. 'DataAdapter updaten; DataTable mitgeben
    18. da.Update(dt)
    19. DataBaseLogger.GetInstance.Log(NLog.LogLevel.Trace, "update datas to database")
    20. If getId Then
    21. Dim idSql As New SqlCeCommand("SELECT @@IDENTITY", cnn)
    22. identity = CInt(idSql.ExecuteScalar)
    23. DataBaseLogger.GetInstance.Log(NLog.LogLevel.Info, "get id from database")
    24. End If
    25. End Using
    26. End Using
    27. End Using
    28. .Close()
    29. DataBaseLogger.GetInstance.Log(NLog.LogLevel.Trace, "closing database connection")
    30. End With
    31. End Using
    32. Return identity
    33. End Function

    Diese Funktion ist aus meinem projekt kopiert, anpassen, NLog-Kram raus nehmen und testen...
    Ansonsten über die verwendeten Klassen informieren, mit den Teilen lade und speichere ich.
    Einfach die dataTables bearbeiten (Datensätze dazu / weg, Update und gut ist)


    Es dürfte eigentlich fast reichen, wenn du bei den Klassen das CE entfernst, ich glaube so heißen die Klassen dann für normales SQL. Die SQL´s selber sind die selben.
    Scheinbar klappt mein (laienhafter) Code; aber die scheinbar leere DB hat physikalisch immer noch die gleiche Größe auf der Festplatte wie als ich noch tausende Datensätze 'drin hatte.
    Kann mir da einer auf die Sprünge helfen?
    Das ist das typische Verhalten der meisten Datenbanken.
    Das hängt mit der Perfomance im laufenden Betrieb zusammen.
    Bei größeren DB-Systemen lauf deshalb nachts Wartungsjobs, um den freien Speicher zu ordnen und die Indexe neu zu berechnen.

    Bei Access kannst du das manuell durch den Menüpunkt "Datenbank komprimieren und reparieren" erledigen.
    Es gibt auch eine Einstellung, dass dies automatisch beim Beenden von Access passiert.
    -> office.microsoft.com/de-ch/acc…ss-datei-HP005187449.aspx
    --
    If Not Program.isWorking Then Code.Debug Else Code.DoNotTouch
    --
    Was mir gerade einfällt (von vorletzter Woche in der Schule) ist, dass eine Datenbank nach dem leeren tatsächlich die selbe Größe hat wie vorher.

    Scheinbar ist es da so, dass jeder Datensatz einen Flag hat, der angibt, ob er gültig ist oder nicht. Beim löschen werden deine Datensätze, die gelöscht werden sollen, als ungültig markiert und sind damit Programmatisch weg, Physikalisch werden sie aber beim nächsten schreiben in die Datenbank überschrieben. Tatsächlich gelöscht werden sie erst, wenn du, wie mein Vorposter erwähnt, die Datenbank "aufräumst", sprich einen Wartungsjob drüber laufen lässt oder sie reparierst.

    Ob es sich bei allen DB´s so verhält, weiß ich nicht, aber gehe einfach mal davon aus, weil auf die Datensätze zugreifen kannst du ja dann nicht mehr, wenn ich es richtig verstanden habe, oder?
    Natürlich verhält es sich bei (fast) allen DBs so.
    Hintergrund ist folgender: Ein doofes "gelöscht... flaggen" dauert nicht lange. Damit die Datenbank performant bleibt und es keine leeren Stellen innerhalb der Datensätze gibt (physikalisch) in denen neue Daten "hieingeschrieben" werden (was wiederum die Suche nach Daten unperformant machen würde), werden gelöschte Daten nur als gelöscht geflagt.
    Größere Datenbanken ordnen sich bei Freizeit automatisch neu (kann man sich wie das Festplattendefragmentieren vorstellen). Access-Datenbanken jedoch nicht. Hier muss mann innerhalb von Access den "Komprimiervorgang" welcher nichts anderes ist, anstoßen.

    Hoffe das war verständlich XD

    PS: Das Komprimieren ist NICHTS anderes als: Neue Datenbank erstellen (unter anderem Namen), alle Tabellen und Abfragen hinein-importieren (gelöschte bleiben außen vor), alte Datenbank löschen und neue Datenbank umbenennen.
    Es war einmal ein kleiner Bär... der wollte eine Geschichte hörn... Da erzählte ihm seine Mutti:
    Es war einmal ein kleiner Bär... der wollte eine Geschichte hörn... Da erzählte ihm seine Mutti:
    Es war einmal ein kleiner Bär... der wollte eine Geschichte hörn... Da erzählte ihm seine Mutti:
    ... Nun solltest es selber wissen. :'D
    Also doch in der Schule aufgepasst ^^
    Es wundert mich gerade nur (abgesehen davon dass es mir nicht selbst aufgefallen ist) dass es anderen nicht aufgefallen ist im Verlauf der Hilfe-Diskussion (keine Kritik an anderen, vielleicht wussten die es nicht...).

    Aber naja, nun sollte es ja funktionieren :)