Neuigkeiten:

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

Mobiles Hauptmenü

Löschabfrage wenn keine DS zum Löschen vorhanden sind

Begonnen von ironpete, September 23, 2016, 14:34:56

⏪ vorheriges - nächstes ⏩

ironpete

Hallo zusammen,

Beim Öffnen der DB werden einmalig alle Daten importiert und die Löschabfrage ist Teil dieser AutoExec Funktion.

Die Löschabfrage sucht nach Duplikaten in tbl A und B  und falls vorhanden, dann löscht sie diese DS aus beiden tbls A und B.

Funktioniert gut, wenn es Duplikate gibt. Wenn nicht, kommt eine Meldung "Löschen nicht möglich" und die AutoExec steigt an dieser Stelle im Code aus.

Wie könnte ich abfangen, dass der Code dort abbricht?

Function AutoExec()
On Error GoTo AutoExec_Err

    DoCmd.SetWarnings False
   
' überprüfen, ob Quelldaten heute bereits aktualisiert wurden
If IsNull(DLookup("Datum", "tbl_Datum", "Datum = Date()")) Then
' falls nicht
    MsgBox ("Daten werden jetzt aktualisiert. Das dauert ca. 5 min.")
    ...
.
.
.
...
    ' kategorisierte Pot BP aus tbl_ICSS_Potential_hist und tbl_CustServ löschen
    DoCmd.OpenQuery "qry_ICSS_Potential_Duplikate_LÖSCHEN", acViewNormal, acEdit
   
    ' Datumtag setzen, damit Daten nur 1x/Tag geladen werden
    DoCmd.OpenQuery "qry_datum_ANFÜGEN", acViewNormal, acEdit
...
...
...
...
    Beep
    MsgBox "Quelldateien aktualisiert", vbInformation, "Aktualisieren aller Quelldateien"
   
Else

Beep
    MsgBox "Daten bereits aktualisiert", vbInformation, "Info"
   End If
   
    DoCmd.SetWarnings True


AutoExec_Exit:
    Exit Function

AutoExec_Err:
    MsgBox Error$
    Resume AutoExec_Exit

End Function


und die Löschabfrage selbst
DELETE DISTINCTROW A.*, B.*, A.OrderNo, B.[Supply Ord], A.OrderLineNo
FROM tbl_ICSS_Potential_hist AS A INNER JOIN tbl_CustServ AS B ON (A.OrderLineNo = B.LineNo) AND (A.OrderNo = B.[Supply Ord])
WHERE (((A.OrderNo)=([B].[Supply Ord])) AND ((A.OrderLineNo)=[B].[LineNo]));

datekk

#1
Notiere dir die Fehlernummer. Setze eine Sprungmarke (hier im Beispiel = "Weiter:") nach der ersten Abfrage. Unten in der Fehlerbehandlung setzt Du die Nummer ein. Wenn dieser Fehler auftritt springt das Programm an die Stelle der Sprungmarke und führt dort den Code fort. Die Abfragen würde ich direkt in die Funktion schreiben.




Function AutoExec()
On Error GoTo AutoExec_Err

dim sql as String

DoCmd.SetWarnings False
   
' überprüfen, ob Quelldaten heute bereits aktualisiert wurden
If IsNull(DLookup("Datum", "tbl_Datum", "Datum = Date()")) Then
' falls nicht
    MsgBox ("Daten werden jetzt aktualisiert. Das dauert ca. 5 min.")
    ...
.
.
.
...
    ' kategorisierte Pot BP aus tbl_ICSS_Potential_hist und tbl_CustServ löschen
sql = "DELETE DISTINCTROW A.*, B.*, A.OrderNo, B.[Supply Ord], A.OrderLineNo FROM tbl_ICSS_Potential_hist AS A INNER JOIN tbl_CustServ AS B ON (A.OrderLineNo = B.LineNo) AND A.OrderNo = B.[Supply Ord]) WHERE (((A.OrderNo)=([B].[Supply Ord])) AND ((A.OrderLineNo)=[B].[LineNo]));"
   
currentdb.execute sql, dbseechanges

Weiter:

    ' Datumtag setzen, damit Daten nur 1x/Tag geladen werden

sql = "**********AbfrageSQLeinsetzen*********"
currentdb.execute sql, dbseechanges


...
...
...
...
    Beep
    MsgBox "Quelldateien aktualisiert", vbInformation, "Aktualisieren aller Quelldateien"
   
Else

Beep
    MsgBox "Daten bereits aktualisiert", vbInformation, "Info"
   End If
   
    DoCmd.SetWarnings True


AutoExec_Exit:
    Exit Function

AutoExec_Err:
    if err.number = xxxxxx Then Goto Weiter
    MsgBox Error$
    Resume AutoExec_Exit

End Function



Access 2016 mit SQL Server Backend. Bereits umgesetzt: Access mit MS SQL Backend,  ADODB Formularbindung, Streamen von Dateien zum SQL Server und zurück (Filestream), Drag&Drop Dateiupload zum Server, CTI / TAPI Integrierung in Access Anwendung - Nutzung auch über Remote Desktop, selbst aktualisierendes Access Frontend auf entfernten Rechnern (Upgrade). Berichte / Kreuztabellen mit SQL Server Backend, Mail Tagging, Outlook Steuerung über Access und umgekehrt // Grundwissen in .Net Core & Blazor Apps

Beaker s.a.

Hallo,
Sprungmarke halte ich für überflüssig, ein einfaches Resume Next sollte hier reichen.
Ausser, zwischen diesen beiden Zeilen steht noch geheimer Code:
currentdb.execute sql, dbseechanges sollte die Zeile sein, die den Fehler wirft, und
' Datumtag setzen, damit Daten nur 1x/Tag geladen werden
wäre die Zeile die von Resume Next angesprungen wird.

gruss ekkehard
Alles, was geschieht, geschieht. - Alles, was während seines Geschehens etwas anderes geschehen lässt, lässt etwas anderes geschehen. - Alles, was sich selbst im Zuge seines Geschehens erneut geschehen lässt, geschieht erneut. - Allerdings tut es das nicht unbedingt in chronologischer Reihenfolge.
(Douglas Adams, Mostly Harmless)

datekk

Habe es nur etwas ausführlicher gemacht, damit bei anderen Fehlern der Code abgebrochen und der Fehler ausgegeben wird. Grundsätzlich geht auch die Variante von Mr. Beaker :)
Access 2016 mit SQL Server Backend. Bereits umgesetzt: Access mit MS SQL Backend,  ADODB Formularbindung, Streamen von Dateien zum SQL Server und zurück (Filestream), Drag&Drop Dateiupload zum Server, CTI / TAPI Integrierung in Access Anwendung - Nutzung auch über Remote Desktop, selbst aktualisierendes Access Frontend auf entfernten Rechnern (Upgrade). Berichte / Kreuztabellen mit SQL Server Backend, Mail Tagging, Outlook Steuerung über Access und umgekehrt // Grundwissen in .Net Core & Blazor Apps

Beaker s.a.

Hallo datekk,
Zitatdamit bei anderen Fehlern der Code abgebrochen und der Fehler ausgegeben wird.
Das kann ja auch bleiben, ich habe ja nur die Sprungmarke kritisiert.

gruss ekkehard
Alles, was geschieht, geschieht. - Alles, was während seines Geschehens etwas anderes geschehen lässt, lässt etwas anderes geschehen. - Alles, was sich selbst im Zuge seines Geschehens erneut geschehen lässt, geschieht erneut. - Allerdings tut es das nicht unbedingt in chronologischer Reihenfolge.
(Douglas Adams, Mostly Harmless)

ironpete

Danke für die Antworten!

Der Code lautet nun


Function AutoExec()
On Error GoTo AutoExec_Err

dim sql as String

DoCmd.SetWarnings False
   
' überprüfen, ob Quelldaten heute bereits aktualisiert wurden
If IsNull(DLookup("Datum", "tbl_Datum", "Datum = Date()")) Then
' falls nicht
    MsgBox ("Daten werden jetzt aktualisiert. Das dauert ca. 5 min.")
    ...
.
.
.
...
    ' kategorisierte Pot BP aus tbl_ICSS_Potential_hist und tbl_CustServ löschen
sql = "DELETE DISTINCTROW A.*, B.*, A.OrderNo, B.[Supply Ord], A.OrderLineNo FROM tbl_ICSS_Potential_hist AS A INNER JOIN tbl_CustServ AS B ON (A.OrderLineNo = B.LineNo) AND A.OrderNo = B.[Supply Ord]) WHERE (((A.OrderNo)=([B].[Supply Ord])) AND ((A.OrderLineNo)=[B].[LineNo]));"
   
resume next

currentdb.execute sql, dbseechanges



    ' Datumtag setzen, damit Daten nur 1x/Tag geladen werden

sql = "**********AbfrageSQLeinsetzen*********"
currentdb.execute sql, dbseechanges


...
...
...
...
    Beep
    MsgBox "Quelldateien aktualisiert", vbInformation, "Aktualisieren aller Quelldateien"
   
Else

Beep
    MsgBox "Daten bereits aktualisiert", vbInformation, "Info"
   End If
   
    DoCmd.SetWarnings True


AutoExec_Exit:
    Exit Function

AutoExec_Err:
    if err.number = xxxxxx Then Goto Weiter
    MsgBox Error$
    Resume AutoExec_Exit

End Function




so kommt aber die Meldung "Resume next ohne Fehler" und der code wird verlassen. Ohne das resume next läuft er weiter und der nächste Befehl wird ausgeführt.


Was macht resume next (weitermachen trotz evtl. Fehlermeldung?)

und was dbSeeChanges?

MzKlMu

#6
Hallo,
if err.number = xxxxxx Then Resume Next
Für xxxxxx muss auch die entsprechende Fehlernummer angeben werden.
Die Sprungmarke "weiter" ist auch gar nicht vorhanden.

Wenn die Fehlernummer nicht ausgewertet werden soll geht es auch so:
AutoExec_Err:
    Resume Next
End Function
Gruß Klaus

ebs17

#7
Wenn ich mich mal reinhänge: Eine ordentlich formulierte Löschabfrage löscht die ausgewählten Datensätze. Wenn es nichts zu löschen gibt, passiert dann eben nichts, auch keine Fehlermeldung.
Somit könnte man sich (mal wieder) besser mit "fehlerfreien" Anweisungen beschäftigen statt sich in Fehlerbehandlungen zu verlieren oder gar eine Programmsteuerung über Fehlerbehandlung vorzunehmen.

Eine (selbstredend notwendige) Fehlerbehandlung sollte nicht nur meiner Meinung nach überwiegend nur bei UNERWARTETEN Fehlern einspringen. Vorhandene bzw. nichtvorhandene Datensätze bei eigener Filterung sind nun wahrlich keine unerwartbaren Zustände.
Um es mal so auszudrücken: Den Airbag eines Autos möchte ich nicht in Aktion kennenlernen.

Zum Löschen: Das würde ich stets nur auf eine Tabelle anwenden, wie  auch alle sonstigen schreibenden Aktionen wie Insert oder Update. Das klappt dann immer, sofern man keine Forderungen der eingestellten referentiellen Integrität verletzt.
Bei mehreren Tabellen nutzt man eine Löschweitergabe, oder man verwendet eine Abfrage pro Tabelle.

Sowie dann auch:
ZitatBeim Öffnen der DB werden einmalig alle Daten importiert und die Löschabfrage ist Teil dieser AutoExec Funktion.

Die Löschabfrage sucht nach Duplikaten in tbl A und B  und falls vorhanden, dann löscht sie diese DS aus beiden tbls A und B.
Wenn man nicht ALLES importiert, sondern nur Gewünschtes, entfallen automatisch solche Löschaktionen. Etwas Plan reduziert Aktionismus.
Siehe auch Grundlagen - SQL ist leicht (4) - Aktualisierung einer Tabelle.
Mit freundlichem Glück Auf!

Eberhard

ironpete

Moin Eberhard, jetzt hast Du aber einen rausgelassen.

Ich meine, ja, danke für die vielen theoretischen Empfehlungen. Kann ich Dir auf meinem Fachgebiet auch geben. Dann schreibe ich Dir auch gerne dazu, "etwas Plan kann nicht schaden", auch wenn ich als Vollspezi immer mehr Plan haben werde und die Nichtspezies eigtl. nie genügend davon haben werden.... Wie auch immer, leider war Deine Beitrag nicht förderlich in der Sache. Weder nach links noch nach rechts  ;) P.S. Beim Reinladen werden geplanterweise etliche Sachen rausgefiltert und diese Duplikate gehören nicht dazu.

Back zum topic: An welcher Stelle bzw. wie kann ich die Löschabfrage besser formulieren? Habe es auch noch nicht gehabt, dass sich eine Löschabfrage aufhängt, wie in meinem Fall. Für mich ist sie schon so komplex, dass ich keine Idee habe, wie ich sie umbasteln könnte. Und sie funktioniert bei Treffern.

@MzKlMu
danke für den Hinweis. Sprungmarke wollte ich verzichten und den xxxxxx habe ich übersehen, der muss weg.