Fehlerhaftes SQL-Statement, ich erkenne einfach das Problem nicht

Hallo, ich habe folgenden SQL-Code, der sowohl unter PSQL als auch MSSQL nicht funktioniert und irgendwie erkenne ich das Problem nicht. Der Code wird von einer Engine generiert, deswegen wirkt er etwas kryptisch.

Code:

DELETE FROM ((FB_VZKKKontenMWWaeh AS T504 LEFT OUTER JOIN FB_VZKKKontenMW AS T503_0 ON T504.VZKKWertID=T503_0.ID)LEFT OUTER JOIN FB_Buchungsperioden AS T378_1 ON T503_0.PeriodeID=T378_1.ID) WHERE (((T378_1.MandantID=4000000000000000010)))

Der PSQL sagt:
ERROR: Syntaxfehler bei »(«
LINE 1: DELETE FROM ((FB_VZKKKontenMWWaeh AS T504 LEFT OUTER JOIN FB…
^

FEHLER: Syntaxfehler bei »(«
SQL state: 42601
Character: 13

Der MSSQL sagt:

Bei einem DELETE FROM kann man keine Outer Joins verwenden (weder im SQL Standard noch in Postgres).

Postgres unterstützt ein DELETE FROM … USING um einen join zu simulieren

Etwa in der Art:

DELETE FROM FB_VZKKKontenMWWaeh AS T504 
  using FB_VZKKKontenMW AS T503_0, 
        FB_Buchungsperioden AS T378_1 
WHERE T504.VZKKWertID = T503_0.ID 
  AND T503_0.PeriodeID = T378_1.ID 
  AND T378_1.MandantID = 4000000000000000010

Das wäre aber ein “inner join”, kein “outer join”.

1 „Gefällt mir“

Ah, danke dir. Dann werde ich das mal umschreiben müssen. Danke auf jeden Fall für den korrekten SQL-Code.

Ob er “korrekt” ist - also wirklich das löscht was gewollt ist - musst Du auf jeden Fall nochmal prüfen. Da der outer join durch die WHERE Bedingung eigentlich gar keiner mehr ist, passt es vermutlich. Aber testen muss man das auf jeden Fall.

Durch die letzte Bedingung (T378_1.MandantID = 4000000000000000010) ist sowieso sichergestellt, daß es sich um Inner Joins handelt — es können keine NULL-Werte dazukommen.
Damit ist die Übersetzung völlig korrekt!

Ich habe jetzt noch die Empfehlung bekommen, den SQL-Code so umzuschreiben:

DELETE FROM FB_VZKKKONTENMWWAEH

WHERE FB_VZKKKONTENMWWAEH.VZKKWERTID

IN (
      SELECT FB_VZKKKONTENMW.ID
      FROM FB_VZKKKONTENMW, FB_BUCHUNGSPERIODEN
      WHERE FB_BUCHUNGSPERIODEN.MANDANTID=4000000000000000010 AND FB_VZKKKONTENMW.PERIODEID=FB_BUCHUNGSPERIODEN.ID
    )

Hier sind auch die AS-Klauseln weg, so dass sich dass auch besser liest.

Viele Grüße, Karsten.

Ja, IN geht natürlich auch - und hat den Vorteil dass es dann auf jedem Datenbanksystem funktioniert.

Meistens ist eine EXISTS Bedingung aber schneller:

DELETE FROM fb_vzkkkontenmwwaeh
WHERE EXISTS (SELECT * 
              FROM fb_vzkkkontenmw
                JOIN fb_buchungsperioden ON fb_vzkkkontenmw.periodeid = fb_buchungsperioden.id 
              WHERE fb_buchungsperioden.mandantid = 4000000000000000010
                AND fb_vzkkkontenmw.id = fb_vzkkkontenmwwaeh.vzkkwertid)

(Ich verwende keine impliziten joins in der WHERE Bedingung, sondern ausschließlich explizite JOIN Operator - aber Du kannst das Sub-Select natürlich weiterhin so schreiben wie Du es lieber magst, das macht keinen Unterschied)

Ah, gut, ich habe mir diesen Code mal gemerkt, wenn er schneller läuft, umso besser. Die hier zu löschenden Datensätze können so bis in den 4-stelligen Bereich gehen.

Danke und Gruß, Karsten.