Neuigkeiten:

Wenn ihr euch für eine gute Antwort bedanken möchtet, im entsprechenden Posting einfach den Knopf "sag Danke" drücken!

Mobiles Hauptmenü

Datenbank mittendrin komprimieren

Begonnen von sellrich, März 07, 2019, 12:29:28

⏪ vorheriges - nächstes ⏩

sellrich

Hallo ihr lieben,

Ich muss in einem Vorgang circa 20 Tabellen löschen bzw. leeren.
Dies geschieht durch:
CurrentDb.Execute DELETE * From tbl1-20 usw.

Jetzt habe ich das Problem, dass die Tabellen so viele Datensätze haben, dass Access mir beim Löschen der 16. Tabelle ein Laufzeitfehler 3035 auswirft (Nicht genügend Systemressourcen - Arbeitsspeicher)
Diesen zu erhöhen ist keine Option.

Ich stelle diese Frage aus reiner Neugierde (ich möchte das Problem anders lösen und werde vermutlich da nochmal auf euch zurückkommen, wenn ich alleine nicht weiterkommen sollte).

Gibt es eine Möglichkeit Codezeilen mittendrin durch ein komprimieren zu unterbrechen und anschließend exakt dort fortzuführen? Ich habe bereits ein Beitrag von DonKarl gelesen, allerdings habe ich das so verstanden, dass ab AC03 sein Beitrag nicht mehr möglich sei?
http://www.donkarl.com?FAQ6.6

MzKlMu

Hallo,
nein, das ist nicht möglich. Beim Komprimieren wird die DB komplett geschlossen, komrimiert und dann wieder geöffnet.

PS:
Solche Tabellen gehören in ein separates Backend, das dann beim Schließen komprimiert wird. Dann dürfte sich das Problem erledigt haben.
Gruß Klaus

sellrich

Zitat von: MzKlMu am März 07, 2019, 12:35:14
PS:
Solche Tabellen gehören in ein separates Backend, das dann beim Schließen komprimiert wird. Dann dürfte sich das Problem erledigt haben.
Sind sie. Und das BE wird auch komprimiert beim schließen. Hätte ja sein können, dass es ein Trick 17 gibt. Schade! Danke für die schnelle Antwort.

Josef P.

Hallo!

Wenn der Code in einer anderen Datei ausgeführt wird, sollte das schon möglich sein: http://www.donkarl.com?FAQ6.7
Die Verbindung zum Backend sollte dann allerdings geschlossen sein.

zum Fehler "zu wenig Arbeitsspeicher":
Wie löscht du? Lässt du alles innerhalb einer Transaktion laufen?
Wäre es möglich, dass du statt dem Löschen der Datensätze die ganze Tabelle löscht und neu erstellst?

mfg
Josef

sellrich

Zitat von: Josef P. am März 07, 2019, 13:11:49
zum Fehler "zu wenig Arbeitsspeicher":
Wie löscht du? Lässt du alles innerhalb einer Transaktion laufen?
Wäre es möglich, dass du statt dem Löschen der Datensätze die ganze Tabelle löscht und neu erstellst?

Was meinst du mit "Wie löscht du"?

Die Tabellen sind SQL Tabellen. Und in mein Access verknüpft.
Daher ist löschen und neu erstellen kein Weg für mich.

Ich hab aber ein kleinen "Schummelweg" gefunden.
Ich lösche 60% danach startet via VBA ne Batch die wider rum Access beendet, komprimiert und es wieder öffnet. Dadurch beginnt der Prozess zwar von vorne - da aber die Ersten 60% bereits gelöscht sind dauerts nur Sekunden bis er beim aktuellen Stand angekommen ist - mit komprimierter Datenbank.

Josef P.

Hallo!

"SQL-Tabelle" sind Tabellen im SQL-Server? ... dann lösch die Datensätze doch direkt per ADODB/OLEDB oder über eine PT-Abfrage im SQL-Server und nicht über die verknüpfte Tabelle.

ZitatWas meinst du mit "Wie löscht du"?
Auf welche Art du löscht. Löscht du per SQL-Anweisung (DAO oder ADODB), über das Docmd-Zeugs oder über ein Recordset.

mfg
Josef

sellrich

Zitat von: Josef P. am März 07, 2019, 14:22:57
Hallo!
"SQL-Tabelle" sind Tabellen im SQL-Server? ... dann lösch die Datensätze doch direkt per ADODB/OLEDB oder über eine PT-Abfrage im SQL-Server und nicht über die verknüpfte Tabelle.

Sorry - meine Kenntnisse beschränken sich leider auf das nötigste. Ich muss diese Prozedur automatisiert durchlaufen lassen. Nachts. Und ja die Tabellen sind innerhalb eines SQL-Express Servers.

Zitat von: Josef P. am März 07, 2019, 14:22:57
Auf welche Art du löscht. Löscht du per SQL-Anweisung (DAO oder ADODB), über das Docmd-Zeugs oder über ein Recordset.

Ich lösche mit CurrentDB.Execute.
Kenne mich mit DAO oder ADODB leider überhaupt nicht aus.

Josef P.

CurrentDB.Execute ist DAO.

Zum Ausprobieren (Code gehört verbessert):

Bei dir sieht der Code aktuall vermutlich so ähnlich aus:
CurrentDB.Execute "delete from DeineTabelle"
Tausche diese Zeile zum Testen mit folgendem Code aus:
'CurrentDB.Execute "delete from DeineTabelle"

Dim db As DAO.Database
Dim qdf As DAO.QueryDef

Set db = CurrentDb
Set qdf = db.CreateQueryDef("")
qdf.ReturnsRecords = False
qdf.Connect = db.TableDefs("DeineTabelle").Connect
qdf.SQL = "delete from " &  db.TableDefs("DeineTabelle").SourceTableName
qdf.Execute
qdf.Close

Damit wird mittels Pass-Through-Abfrage die Delete-Anweisung an den Server weitergegeben.

mfg
Josef

sellrich

Josef P. Danke für diesen Hinweis.
Meine Frage hierzu wäre noch, da ich ja 20 Tabellen habe muss ich für jede Tabelle diesen Code ausführen ? oder reicht es wenn ich die Zeilen
qdf.Connect = db.TableDefs("DeineTabelle").Connect
qdf.SQL = "delete from " &  db.TableDefs("DeineTabelle").SourceTableName
qdf.Execute


wiederhole jedoch immer mit anderen Tabellennamen?

So sozusagen :


Dim db As DAO.Database
Dim qdf As DAO.QueryDef

Set db = CurrentDb
Set qdf = db.CreateQueryDef("")
qdf.ReturnsRecords = False
qdf.Connect = db.TableDefs("DeineTabelle1").Connect
qdf.SQL = "delete from " &  db.TableDefs("DeineTabelle1").SourceTableName
qdf.Execute
qdf.Connect = db.TableDefs("DeineTabelle2").Connect
qdf.SQL = "delete from " &  db.TableDefs("DeineTabelle2").SourceTableName
qdf.Execute
qdf.Close

Josef P.

Wie geschrieben, der Code war nur zum Testen gedacht und gehört optimiert.

Beispiel (ungetester Luftcode, der nur das Prinzip zeigen soll):
Dim db As DAO.Database
Dim qdf As DAO.QueryDef

Set db = CurrentDb
Set qdf = db.CreateQueryDef("")
qdf.ReturnsRecords = False
qdf.Connect = db.TableDefs("DeineTabelle1").Connect ' oder fix den Connectionstring als Text übergeben
' da es immer die gleiche Datenbank sein wird, reicht es aus, die Connection nur einmal einzustellen

Dim TableNameArray() as variant
dim TabArrayItm as Variant
TableNameArray = Array("Tabelle1", "Tabelle2", ..., "Tabelle0815")
' oder gleich den Tabnamen vom SQL-Server verwenden:
' TableNameArray = Array("dbo.Tabelle1", "dbo.Tabelle2", ..., "dbo.Tabelle0815")

for each TabArrayItm in TableNameArray
       qdf.SQL = "delete from " &  db.TableDefs(TabArrayItm ).SourceTableName
       ' oder mit SQL-TabNamen: (läuft theoretisch schneller, da nicht auf die Access-Tabelle zugegriffen werden muss
       '               praktisch wird es nicht merkbar langsamer sein
       'qdf.SQL = "delete from " &  TabArrayItm
       qdf.Execute
next

qdf.Close

Anm.: Ich würde diesen Code noch in Hilfsprozeduren aufteilen, aber das wird an dieser Stelle vielleicht zu unübersichtlich.

mfg
Josef

sellrich

Vielen Dank für diese Hilfe bis hierhin. Ich werde es testen und Rückmeldung geben sobald ich was erreicht habe.

Josef P.

Es geht übrigens noch kürzer, da man per PT mehrere SQL-Anweisungen an den Server geben kann.

' 1. SQL-Anweisung zusammensetzen
Dim SqlText as String
Dim TableNameArray() as variant
dim TabArrayItm as Variant

TableNameArray = Array("Tabelle1", "Tabelle2", ..., "Tabelle0815")
' oder gleich den Tabnamen vom SQL-Server verwenden:
' TableNameArray = Array("dbo.Tabelle1", "dbo.Tabelle2", ..., "dbo.Tabelle0815")

for each TabArrayItm in TableNameArray
      SqlText  = SqlText  & "delete from " &  db.TableDefs(TabArrayItm ).SourceTableName & ";" & vbnewline
       ' oder mit SQL-TabNamen: (läuft theoretisch schneller, da nicht auf die Access-Tabelle zugegriffen werden muss
       '               praktisch wird es nicht merkbar langsamer sein
       'SqlText   = "delete from " &  TabArrayItm & ";" & vbnewline
next

' 2. SQL-Anweisung ausführen
Dim db As DAO.Database
Dim qdf As DAO.QueryDef

Set db = CurrentDb
Set qdf = db.CreateQueryDef("")
qdf.ReturnsRecords = False
qdf.Connect = db.TableDefs("DeineTabelle1").Connect ' oder fix den Connectionstring als Text übergeben
qdf.SQL = SqlText 
qdf.Execute

Mit dieser Variante wird nur einmal eine Verbindung zum Server aufgebaut und die SQL-Anweisung übertragen.

Anm.: für den SQL-Server gibt es auch die Truncate-Anweisung zum Löschen aller Datensätze aus einer Tabelle.

mfg
Josef

ebs17

ZitatIch muss in einem Vorgang circa 20 Tabellen löschen bzw. leeren.
Ich staune, dass das nicht schon an sich in Frage gestellt wird. Wenn man durch Löschen(!) an Kapazitätsgrenzen stößt wie auch immer, ist da m.M. im Umfeld etwas sehr misslungen und bedarf einer grundsätzlichen Analyse statt etwas Verarbeitungskosmetik.

Wenn der SQL Server Express am Limit ist, müsstest Du upgraden oder die Temp-Müll-Schleuder in ein eigenes Backend verlegen.

Könnte aber auch sein, dass man sich hier ein Frontend-Problem erzeugt hat. Da sollte man ebenso überprüfen, was man da tut.
Mit freundlichem Glück Auf!

Eberhard

sellrich

Zitat von: sellrich am März 07, 2019, 12:29:28
Ich muss in einem Vorgang circa 20 Tabellen löschen bzw. leeren.

Ich stelle diese Frage aus reiner Neugierde (ich möchte das Problem anders lösen und werde vermutlich da nochmal auf euch zurückkommen, wenn ich alleine nicht weiterkommen sollte).
Auch an dem Punkt wieder mal vielen Dank für deine kritische und Lösungsorientierte Antwort. Zeigt einem sehr deutlich auf in was für einem Kauderwelsch von AccessKram ich mich hier bewegen muss  ???

Das das keine Lösung ist ist mir durchaus bewusst. Wie bereits erwähnt, stelle ich diese Frage auch nur aus reiner Neugierde. Nur um rundum eben etwas mehr Kenntnisse zu erhalten.
Die Notwendigkeit des ständigen Löschen um ein sauberes neubefüllen zu gewährleisten ist auf dem "Mist" meines Vorgängers gewachsen.
Dies besser zu machen bzw. anders zu lösen liegt (noch!) nicht innerhalb meines Könnens.

Der Post von Josef zb. erweitert mein Kenntnisstand, da ich bisher noch nie mit Arrays gearbeitet habe und mich damit erstmal grundlegend befassen muss.

ebs17

ZitatNotwendigkeit des ständigen Löschen um ein sauberes neubefüllen zu gewährleisten
Damit kannst Du dann nicht mehr sagen, Du hättest es nicht gewusst: Grundlagen - SQL ist leicht (4) - Aktualisierung einer Tabelle
Mit freundlichem Glück Auf!

Eberhard