Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Datenbanken (https://www.delphipraxis.net/15-datenbanken/)
-   -   Seltsames Phänomen mit ExexSQL (https://www.delphipraxis.net/196307-seltsames-phaenomen-mit-exexsql.html)

norwegen60 10. Mai 2018 10:43

Datenbank: MsSAL • Version: 2014 • Zugriff über: TADoQuery

Seltsames Phänomen mit ExexSQL
 
Hallo zusammen,

ich habe das Problem, dass mit folgendem Aufruf nicht sichergestellt ist, dass die Daten in der DB gelöscht werden obwohl Result = true zurück gegeben wird
Delphi-Quellcode:
var
  lQuery: TAdoQuery;

begin
  lQuery := TAdoQuery.Create(nil);
  lQuery.Connection := GetConnection();
 
  Result := true;
  lQuery.SQL.Text := format('delete Table1 where RelID = %d', [iID]);
  Result := Result and (lQuery.ExecSQL > 0);

  lQuery.SQL.Text := format('delete Table2 where RelID = %d', [iID]);
  Result := Result and (lQuery.ExecSQL > 0);
Insgesamt sind es 4 Tabellen. Manchmal wurden die Daten in allen Tabellen gelöscht, manchmal wurden sie in einer der Tabellen nicht gelöscht.
Nach der Umstellung auf
Delphi-Quellcode:
  Result := 0;
  lQuery.SQL.Text := format('delete Table1 where RelID = %d', [iID]);
  Result := Result + lQuery.ExecSQL;

  lQuery.SQL.Text := format('delete Table2 where RelID = %d', [iID]);
  Result := Result + lQuery.ExecSQL;
werden die Daten jetzt immer gelöscht. Diese Lösung ist eh besser für mich, aber ich frag mich trotzdem was bei der Booleschen Variante schief geht

DeddyH 10. Mai 2018 10:55

AW: Seltsames Phänomen mit ExexSQL
 
Mich wundert eher, dass das Statement ohne FROM überhaupt ausgeführt wird. Und falls es darum gehen sollte, Detaildaten zu einem Mastersatensatz zu löschen, würde ich das eher auf DB-Ebene über eine Löschregel handhaben.

Bernhard Geyer 10. Mai 2018 11:11

AW: Seltsames Phänomen mit ExexSQL
 
Zitat:

Zitat von DeddyH (Beitrag 1401758)
Mich wundert eher, dass das Statement ohne FROM überhaupt ausgeführt wird.

Beim MS SQL-Server ist das FROM ein optionales Schlüsselwort: https://docs.microsoft.com/de-de/sql...ql-server-2017

Zitat:

Zitat von DeddyH (Beitrag 1401758)
Und falls es darum gehen sollte, Detaildaten zu einem Mastersatensatz zu löschen, würde ich das eher auf DB-Ebene über eine Löschregel handhaben.

Wenn du das alles in eine Transaktion packst kann hier nix passieren.


Das Problem ist hier das du den Result-Wert falsch behandelst.
ExecSQL liefert die Anzahl der betroffenen Datensätze zurück. Ist dieser für eine Löschaktion 0, so ist result = False.
Und wenn du im Projekt die Option eingestellt hast, Ausdrücke nur soweit wie nötig auszuführen sorgt ein

Delphi-Quellcode:
Result := Result and (lQuery.ExecSQL > 0);
dafür das nur die Zeile bis zum erkennen von and ausgewertet wird und das ExecSQL nicht mehr aufgerufen wird.

Das ist aber auch nicht nötig. ExecSQL wird ein Exception schmeißen wenn eine Löschaktion nicht erfolgreich sein sollte.

himitsu 10. Mai 2018 13:05

AW: Seltsames Phänomen mit ExexSQL
 
NEIN, wieso sollte das eine Exception werfen? (das passiert nur, wenn es im DBServer eine Exception gab, z.B. durch fehlerhaftes SQL oder falsche Tabellen-/Feld-Namen)
Es konnte nichts gefunden werden, was zu Löschen war, ist KEIN Fehler, aber es konnte was nicht gelöscht werden, weil abhängige Referenz .. das schon.


Delphi-Quellcode:
Result := (lQuery.ExecSQL > 0) and Result;
um es nochmal richtig zu zeigen.

NICHT umstellen, sondern nur die Beschreibung lesen!
http://docwiki.embarcadero.com/RADSt...ler-Direktive)

haentschman 10. Mai 2018 14:07

AW: Seltsames Phänomen mit ExexSQL
 
Moin...8-)

unabhängig vom Problem solltest du immer Parameter benutzen!
siehe: https://de.wikipedia.org/wiki/SQL-Injection

Delphi-Quellcode:
lQuery.SQL.Text := format('delete Table1 where RelID = %d', [iID]);
...
lQuery.SQL.Text := 'delete Table1 where RelID = :ID';
lQuery.ParamByName('ID').AsInteger := iID;

hstreicher 10. Mai 2018 15:06

AW: Seltsames Phänomen mit ExexSQL
 
Boolean Evaluation Shortcircuit {$B-},

wenn das Result aufgrund des Ausdrucks festliegt wird der Rest der Abfrage nicht mehr ausgewertet

also
aus
result=result and (ibquery.execsql>0)

wird
result=result

und das Query wird nie ausgeführt

http://docs.embarcadero.com/products...ation_xml.html

mfg Hannes

edit:hab himitsu s Post übersehen

Bernhard Geyer 10. Mai 2018 16:01

AW: Seltsames Phänomen mit ExexSQL
 
Zitat:

Zitat von himitsu (Beitrag 1401770)
NEIN, wieso sollte das eine Exception werfen? (das passiert nur, wenn es im DBServer eine Exception gab, z.B. durch fehlerhaftes SQL oder falsche Tabellen-/Feld-Namen)

WEnn ein Datensatz wegen einer Regel auf DB-Ebene (Referenzielle Integrität, Zugriffsrechte) nicht gelöscht werden kann, dann gibts auch eine Exception.

Zitat:

Zitat von himitsu (Beitrag 1401770)
NICHT umstellen, sondern nur die Beschreibung lesen!
http://docwiki.embarcadero.com/RADSt...iler-Direktive)

Aber dann schon bitte mit abschließender Klammer: http://docwiki.embarcadero.com/RADSt...ler-Direktive)

norwegen60 20. Mai 2018 09:43

AW: Seltsames Phänomen mit ExexSQL
 
Das fehlende FROM war nicht das Problem. Hatte es nämlich auch so verstanden dass das in MsSQL optional ist. Da es im Source aber unterschiedlich gehandhabt wurde habe ich das vereinheitlicht.
Natürlich war das der Fehler:
Zitat:

Zitat von Bernhard Geyer (Beitrag 1401759)
Und wenn du im Projekt die Option eingestellt hast, Ausdrücke nur soweit wie nötig auszuführen sorgt ein

Delphi-Quellcode:
Result := Result and (lQuery.ExecSQL > 0);
dafür das nur die Zeile bis zum erkennen von and ausgewertet wird und das ExecSQL nicht mehr aufgerufen wird.

Danke
Gerd


Alle Zeitangaben in WEZ +1. Es ist jetzt 10:44 Uhr.

Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz