Neuigkeiten:

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

Mobiles Hauptmenü

[gelöst]: Absturz bei Abfrage

Begonnen von Minotauros, Oktober 02, 2020, 16:51:40

⏪ vorheriges - nächstes ⏩

Minotauros

EDIT2: Ohne das Feld: "Sum(RabattBetrag) AS Rabatt" tritt der Fehler nicht auf.
EDIT: habe einen SQL-String mit fast 1400 Zeichen erfolgreich ausgeführt, kann also nicht an der Länge liegen.

Guten Tag

Heute ist echt der Wurm drin, oder ich stosse gegen eine mir nicht bekannt Grenze von Access:

Ich habe eine Verschachtelte SQL-Abfrage("sqlRabattpreise") als String gespeichert. (ca 924 Zeichen, mehrere Unterabfragen und auch UNION-Klauseln)
Diese Abfrage funktioniert so und kann ausgeführt werden.

Versuche ich nun eine weitere Aggregation draufzupacken, stürzt mein Access ab, sobald die Abfrage ausgeführt werden soll. Die Gesamtlänge von sqlRabatt ist nun 1033 Zeichen:
    sqlRabatt = "SELECT PositionID, Sum(RabattBetrag) AS Rabatt " & _
                "FROM (" & sqlRabattpreise & ") AS Rabattpreise " & _
                "GROUP BY PositionID"
    CurrentDb.QueryDefs("qryRabatt").sql = sqlRabatt

Interessant: Die Länge von sqlRabattpreise ist variabel. Bei kürzeren Varianten funktioniert der Code. Auch funktioniert es wenn ich sqlRabattpreise in einer Abfrage speichere und dann basierend auf dieser Abfrage die Aggregation mache.

https://www.ms-office-forum.net/forum/showthread.php?t=129167#:~:text=Der%20SQL%20String%20wird%20dabei,3500%20Zeichen%20lang%20und%20l%C3%A4nger.

Laut der Aussage unter diesem Link beträgt die maximale Zeichenzahl eines SQL-Strings 64'000 Zeichen.
Die maximale Länge in einer Zelle im Abfragentwurf-Bereich beträgt 1024 Zeichen.

Ich benutze die Zellen im Abfrageentwurf-Bereich nicht, trotzdem beschleicht mich das Gefühl, dass es irgendetwas mit der Anzahl der Zeichen zu tun hat.

Wenn ich nach dem Absturz die Access neu öffne, dann finde ich, dass Access eine neue Abfrage mit einem kryptischen Namen erstellt hat, welche allerdings leer ist:

qryRabatt_7AD614424B4A44C2B77A66E3E1B7D67F

Weiss jemand, was die Ursache dieses Problems ist und wie man es beheben kann?

Vielen Dank und freundliche Grüsse

Mino


ebs17

#1
UNION und Gruppieren/Aggregieren zusammen wäre für mich ein Ausnahmezustand, unabhängig davon, ob es manchmal irgendwie funktioniert. GUT funktionieren kann das nicht.

Beheben?
=> Datenmodellierung überprüfen. UNION ist im Großteil der Fälle eine Folge von unzureichender Strukturplanung.
=> Abfrage anders formulieren. Für eine Rabattsumme pro Position eine Abfrage der Länge von über 1.000 Zeichen in den Ring zu werfen - mit dem 40-Tonner fährt man auch, um seine zwei Frühstücksbrötchen aus der Innenstadt zu holen ...?

Sowie:
Zitatstürzt mein Access ab, sobald die Abfrage ausgeführt werden soll
Wie äußert sich das genau? Gelber Rauch, lila Sternchen, Selbstauflösung der Festplatte?
Oder einfach gefühlte Untätigkeit, weil man dem Rechner eine Rechentätigkeit übergeben hat, an der er eine Weile zu tun hat?
Mit freundlichem Glück Auf!

Eberhard

Minotauros

Guten Tag

Erstmal danke für die Hinweise.

Der Absturz geht wie folgt von statten:

  • Access versucht zu rechnen (Sanduhrsymbol) für ca. 2 Sekunde
  • Access schliesst sich selber komplett.
  • Access startet sich wieder und öffnet ein Fenster um ein Backup zu speichern
  • Danach wird die Datei wieder geöffnet und die Abfrage mit dem komischen Namen wurde hinzugefügt

Der ganze Vorgang dauert nur etwa 10 Sekunden. Ein Fenster um den Fehler an Microsoft zu senden, wie ich es sonst von Windows kenne erscheint nicht.
Gibt es eigentlich irgendwo eine Log-Datei wo man mehr über die Fehlerursache herausfinden kann?

Freundliche Grüsse

DF6GL

Hallo,



-- Prüfe, ob in JEDEM Modulkopf Option Explicit steht.

-- Kompiliere, nachdem das korrigiert wurde, die DB nochmal (VBA-Editor/Debuggen/Kompilieren). Auftretende Fehler allesamt eliminieren.

--  Zeige die SQL-Strings aller beteiligter Abfragen und den vollständigen Code, der am Zusammenbau oder der Verwendung der SQL-Strings beteiligt ist.


-- Lade ansonsten die DB (soweit datenreduziert, als dass die Situation weiterhin auftaucht) gezippt hier hoch.


Viele Grüße vom Bodensee
Franz, DF6GL

Hilfestellung:  http://www.access-o-mania.de/forum/index.php?topic=6969.msg118738#msg118738

Links und Tipps:
1.   http://v.hdm-stuttgart.de/~riekert/lehre/db-kelz/
1a. http://www.tinohempel.de/info/info/datenbank/normalisierung.htm
1b. https://support.office.com/de-de/article/Grundlagen-des-Datenbankentwurfs-eb2159cf-1e30-401a-8084-bd4f9c9ca1f5#bmterms
2.   http://www.donkarl.com
3.   https://web.archive.org/web/20201201233522/http://www.dbwiki.net/
4.   http://www.access-tutorial.de/
5.   http://www.tty1.net/smart-questions_de.htm
6.   http://access.joposol.com/accept

Last but not least:   < F1 > für Hilfe
;) Learning by doing not by spoon-feed ;)

Tipp: Find and Replace for Access

Minotauros

Hallo

Vielen Dank für die Hinweise.

Da es mit dem Zwischenspeichern von SQL-Strings in Abfragen läuft, ist das Problem nicht dringlich. Ich werde mich zu einem späteren Zeitpunkt wieder dem Problem annehmen und gegebenenfalls die DB hochladen.

Habe den gesamten Code mit SQL-Strings, Kommentaren und dem auskommentierten Block der für den Absturz verantwortlich ist angefügt.

Ich werde das Thema trotzdem als gelöst bezeichnen, da ich nicht unnötig eure Zeit in Anspruch nehmen möchte.

Vielen Dank.

'SQL-Abfrage für Aufstellung Rechnung
Private Function Aufstellung()
    Dim sqlNetto As String
    Dim sqlNettopreis As String
    Dim sqlRabatt As String
    Dim sqlRabattKondition As String
    Dim sqlRabattpreise As String
    Dim sqlAufstellung As String
    Dim sqlTotal As String
   
    'BruttoNetto prüfen # getestet:gut
    If Me.BruttoNetto Then
        sqlNettopreis = "Einzelpreis/(1+[MWST-Satz])"
    Else
        sqlNettopreis = "Einzelpreis"
    End If
   
    'Nettopreise berechnen # getestet: gut
    sqlNetto = "SELECT PositionID, Bezeichnung AS Objekt, Menge, " & sqlNettopreis & " AS Nettopreis, Nettopreis*Menge AS NettoBetrag, [MWST-Satz] " & _
               "FROM tblObjekt INNER JOIN (tblMenge INNER JOIN (tblPosition INNER JOIN tblPreis ON tblPosition.PositionID = tblPreis.Position_F)" & _
                    " ON tblMenge.Position_F = tblPosition.PositionID) ON tblObjekt.ObjektID = tblMenge.Objekt_F " & _
               "WHERE tblPosition.Liste_F = " & Me.subStueckliste.Form!ListeID
    CurrentDb.QueryDefs("qryNetto").sql = sqlNetto
   
    'Rabatt-Konditionen Abfrage erstellen # getestet: gut
    sqlRabattKondition = "SELECT Position_F, Kondition, EinschraenkungPosition, Frist, Ermaessigung " & _
                           "FROM tblKondition INNER JOIN tblPosition ON tblPosition.PositionID = tblKondition.Position_F " & _
                           "WHERE Liste_F = " & Me.subZahlungskonditionen.Form!ListeID & " AND Typ = ""Rabatt"";"
    CurrentDb.QueryDefs("qryRabattKondition").sql = sqlRabattKondition
                           
    'Rabatt-Konditionen auslesen und SQL-String erzeugen # getestet: gut
    Dim dbsCurrentDB As DAO.Database
    Set dbsCurrentDB = CurrentDb()
    Dim rstKondition As DAO.Recordset
    Set rstKondition = dbsCurrentDB.OpenRecordset(sqlRabattKondition, dbOpenSnapshot, dbReadOnly)
    'Prüfen ob Abfrage Datensätze enthält
    If rstKondition.BOF = False Then
        sqlRabattpreise = "SELECT PositionID, RabattBetrag FROM ("
        Do Until rstKondition.EOF
            sqlRabattpreise = sqlRabattpreise & "SELECT PositionID, NettoBetrag*" & rstKondition!Ermaessigung & " AS RabattBetrag " & _
                                                 "FROM (" & sqlNetto & ") AS Netto"
            If Not IsNull(rstKondition!EinschraenkungPosition) Then
                sqlRabattpreise = sqlRabattpreise & " WHERE PositionID " & rstKondition!EinschraenkungPosition
            End If
            sqlRabattpreise = sqlRabattpreise & " UNION ALL "
            rstKondition.MoveNext
        Loop
        'Letzte 10 Zeichen aus String entfernen, Alias vergeben und Klammer setzen
        sqlRabattpreise = Left(sqlRabattpreise, Len(sqlRabattpreise) - 10) & ") AS Nettopreise"
    Else
        sqlRabattpreise = "SELECT PositionID, 0 AS RabattBetrag " & _
                          "FROM (" & sqlNetto & ")"
    End If
   
    'DAO-Objekte schliessen
    rstKondition.Close
    dbsCurrentDB.Close
    Set dbsCurrentDB = Nothing
    Set rstKondition = Nothing
   
    CurrentDb.QueryDefs("qryRabattpreise").sql = sqlRabattpreise
   
'Auskommentiert aufgrund Absturz
''    Rabatte Gruppieren # getestet: gut, Test UNION-Abfrage hängig
'    sqlRabatt = "SELECT PositionID, Sum(RabattBetrag) AS Rabatt " & _
'                "FROM (" & sqlRabattpreise & ") AS Rabattpreise " & _
'                "GROUP BY PositionID"
'    CurrentDb.QueryDefs("qryRabatt").sql = sqlRabatt
   
    sqlRabatt = "SELECT PositionID, Sum(RabattBetrag) AS Rabatt " & _
                "FROM qryRabattpreise AS Rabattpreise " & _
                "GROUP BY PositionID"
    CurrentDb.QueryDefs("qryRabatt").sql = sqlRabatt
   
    'Skonto auslesen # getestet: gut
    Dim Skonto As Variant
    Skonto = CDec(DLookup("[Ermaessigung]", "tblKondition", "[Position_F]=" & Me.cboSkonto_F))
                           
    'Tabellen Netto und Rabatt zusammenfügen # getestet: gut
    sqlAufstellung = "SELECT Netto.PositionID, Objekt, Menge, Nettopreis, [MWST-Satz], NettoBetrag, Rabatt AS RabattBetrag, Nettobetrag*" & Skonto & " AS SkontoBetrag, " & _
                                "NettoBetrag-RabattBetrag-SkontoBetrag AS NettoNetto, [MWST-Satz]*NettoNetto AS MWSTBetrag, NettoNetto+MWSTBetrag AS BruttoBetrag " & _
                     "FROM (" & sqlRabatt & ") AS Rabatt INNER JOIN (" & sqlNetto & ") AS Netto ON Rabatt.PositionID = Netto.PositionID"
    CurrentDb.QueryDefs("qryAufstellung").sql = sqlAufstellung
   
    'Aggregationen bilden # getestet: gut
    sqlTotal = "SELECT Sum(NettoBetrag) AS NettoSumme, Sum(RabattBetrag) AS RabattSumme, Sum(SkontoBetrag) AS SkontoSumme, Sum(NettoNetto) AS NettoNettoSumme, " & _
                        "Sum(MWSTBetrag) AS Summe_MWST, Sum(BruttoBetrag) AS SummteTotal " & _
               "FROM (" & sqlAufstellung & ") AS Aufstellung;"
    CurrentDb.QueryDefs("qryTotal").sql = sqlTotal
   
    'Aufstellung aktualisieren
    Me!subAufstellung.Form.RecordSource = sqlTotal
    Me.subAufstellung.Form.Requery
                   
End Function

DF6GL

Hallo,

naja,

Du könntest ja noch den Inhalt von "sqlRabatt" mit Debug.Print in das Direktfenster schreiben und hier mit C&P posten...

Viele Grüße vom Bodensee
Franz, DF6GL

Hilfestellung:  http://www.access-o-mania.de/forum/index.php?topic=6969.msg118738#msg118738

Links und Tipps:
1.   http://v.hdm-stuttgart.de/~riekert/lehre/db-kelz/
1a. http://www.tinohempel.de/info/info/datenbank/normalisierung.htm
1b. https://support.office.com/de-de/article/Grundlagen-des-Datenbankentwurfs-eb2159cf-1e30-401a-8084-bd4f9c9ca1f5#bmterms
2.   http://www.donkarl.com
3.   https://web.archive.org/web/20201201233522/http://www.dbwiki.net/
4.   http://www.access-tutorial.de/
5.   http://www.tty1.net/smart-questions_de.htm
6.   http://access.joposol.com/accept

Last but not least:   < F1 > für Hilfe
;) Learning by doing not by spoon-feed ;)

Tipp: Find and Replace for Access