Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Datenbanken (https://www.delphipraxis.net/15-datenbanken/)
-   -   Delphi TAdoQuery Parameters.DataType ändert sich nach SQL.Add (https://www.delphipraxis.net/216588-tadoquery-parameters-datatype-aendert-sich-nach-sql-add.html)

berens 23. Jan 2025 14:45

Datenbank: Access .mdb • Version: - • Zugriff über: TAdoConnection

TAdoQuery Parameters.DataType ändert sich nach SQL.Add
 
Edit: Diesen Beitrag 1:1 bei ChatGPT liefert dann doch eine sinnvolle Antwort. Der Wert TAdoQuery.Paramcheck ist per definition Schuld daran:
Code:
Gibt an, ob die Parameterliste der ADO-Datenmenge neu erstellt wird, wenn sich zur Laufzeit die SQL-Anweisung ändert.
Gnaaa.

Thema damit erstmal ERLEDIGT, falls nicht jemand eine tolle idee hat, wie ich arbeiten kann, ohne jeden Parameter mit ".Create" manuell anzulegen...

Danke für eure Aufmerksamkeit, der Beitrag kann gerne gelöscht werden.

----

Hallo zusammen,
dank ChatGPT und Google bekommt man ja selbst immer mehr alleine gelöst, aber bei diesem Problem stehe ich vor einem Rätsel.

Hier seht ihr die gekürzte Methode, die so seit > 20 Jahren "Fehlerfrei" im Einsatz ist.
Fehlerfrei deswegen in Anführungszeichen, weil SPORADISCH die Exception "Datentypen in Kriterienausdruck unverträglich" kommt.
Nach langem hin und her kann ich es jetzt in diesem Moment gerade auf meinem PC dauerhaft reproduzieren, und habe dabei festgestellt,
dass durch die Ausführung von q.SQL.Add(' ORDER BY Termine.Von;') der q.Parameters.ParamByName('Jetzt1').DataType trotz der manuellen Festlegung auf ftDateTime auf ftWideString springt.

Das ist einerseits total unerwartet, da ich diesen oben explizt festgelegt habe. Andererseits wundert es mich, dass dieser Fehler dann nicht dauerhaft vorkommt.

Ich habe dazu auf die Schnelle nun im Internet keine "Einschränkungen" finden können, würde aber anhand des Fehlerbildes folgendende Erkenntnisse "definieren":
Code:
Der DataType der Parameter kann sich unerwartet, automatisch, und "ins Falsche" ändern, wenn nach der Zuweisung des Parameters mit "SQL.Add" weiterer SQL-Text hinzugefügt wird, oder wahrscheinlich auch, wenn der SQL.Text anderweitig geändert wird --> Parameter dürfen erst dann hinzugefügt werden, wenn der SQL-Text fertig ist!
Auch habe ich paranoide Bedenken, dass sich der DataTyp schon bei der Zuweisung von "Jetzt1" ändern könnte, wenn Delphi vielleicht der Meinung ist, einen besseren Datentyp zu finden, als den, den ich gebe (sonst würde es ja auch später nicht auf ftWideString springen... :roll:).
q.Parameters.ParamByName('Jetzt1').DataType := ftDateTime;
q.Parameters.ParamByName('Jetzt1').Value := _Jetzt;
--> soll ich hier jetzt nochmal (oder stattdessen?) DataType := ftDateTime; machen?

Ist bekannt, WARUM oder durch welchen AUSLÖSER der DataType meines Parameters sich ändert, bzw. ist es normal, dass das bei q.SQL.ADD passiert, dass den Parametern ein neuer Datentyp zugeordnet werden könnte?
Ist dazu irgendwas dokumentiert, wonach muss ich suchen?

Oder ist das wieder so ein Programmierer-Moment nach dem Motto: "Entschuldigung, das steht auf der ersten Seite des Handbuchs von TAdoQuery, dass man nach dem Zuweisen der Parameter den SQL-Text nicht mehr verändern darf?".

Da ich im realen Programm das Query ein wenig komplexer Aufbauen muss, mit vielen Wenn-Danns, die sich auf einzelne Abschnitte und die Anzahl der Parameter sehr stark auswirken, wäre es fatal falls dies tatsächlich erwartet wird. Erst mit allen Wenn-Danns den SQL-Text verfassen, und dann erst mit allen Wenn-Danns die Parameter zu setzen scheint mit etwas ... abstrus? Bin ich der einzige Programmierer der das SQL-Query über mehrere Methoden verteilt zusammensetzen lässt (Füge Filter nach Auswahl des Benutzer hinzu; Füge Sortierung nach Auswahl des Benutzers hinzu, ...)?

Delphi-Quellcode:
procedure Database_SELECT_ALL_FROM_Termine_Jetzt(q: TAdoQuery; _Jetzt: TDateTime);
var
  t: string;
begin
  if not assigned(q) then Exit;

  try
    CloseQueryAndClearSQLTextAndParameters(q);

      t := ' SELECT *' +
           ' FROM Termine' +
           ' WHERE '                                  + #13#10 +
           '    ( Termine.EinblendZeit <= :Jetzt1 ) ' + #13#10 +
           '    AND '                                + #13#10 +
           '    ( Termine.AusblendZeit > :Jetzt2 ) ';

      q.SQL.Add(t);

      q.Parameters.ParamByName('Jetzt1').DataType := ftDateTime;
      q.Parameters.ParamByName('Jetzt1').Value   := _Jetzt;

      q.Parameters.ParamByName('Jetzt2').DataType := ftDateTime;
      q.Parameters.ParamByName('Jetzt2').Value   := _Jetzt;

    q.SQL.Add(' ORDER BY Termine.Von;');

    OpenQueryAndLogIfFailed(q, P);
  except
//...
  end;

  if not q.Active then begin
    Clipboard.AsText := q.SQL.Text;
    sleep(0);
  end;
end;
Delphi 10.4

Delphi.Narium 23. Jan 2025 16:45

AW: TAdoQuery Parameters.DataType ändert sich nach SQL.Add
 
Grundsätzlich baue ich zuerst das SQL vollständig zusammen und dann werden die Parameter mit Werten befüllt. Ich käme nie auf die Idee ein SQL teilweise zu erstellen, dann Parameter zu befüllen und dann das SQL zu erweitern ...

Daher hab' ich das von Dir beschriebene Problem wohl auch noch nie gehabt.
Delphi-Quellcode:
  try
    CloseQueryAndClearSQLTextAndParameters(q);

      t := ' SELECT *' +
           ' FROM Termine' +
           ' WHERE '                              + sLineBreak +
           ' ( Termine.EinblendZeit <= :Jetzt1 ) ' + sLineBreak +
           ' AND '                                + sLineBreak +
           ' ( Termine.AusblendZeit > :Jetzt2 ) ';

      q.SQL.Add(t);
      q.SQL.Add(' ORDER BY Termine.Von;');

      q.Parameters.ParamByName('Jetzt1').DataType := ftDateTime;
      q.Parameters.ParamByName('Jetzt1').Value := _Jetzt;
      q.Parameters.ParamByName('Jetzt2').DataType := ftDateTime;
      q.Parameters.ParamByName('Jetzt2').Value := _Jetzt;
    OpenQueryAndLogIfFailed(q, P);
  except
//...
  end;
Wobei nicht einfach so?
Delphi-Quellcode:
      q.SQL.Add(' SELECT *');
      q.SQL.Add(' FROM Termine');
      q.SQL.Add(' WHERE ');
      q.SQL.Add(' ( Termine.EinblendZeit <= :Jetzt1 ) ');
      q.SQL.Add(' AND ');
      q.SQL.Add(' ( Termine.AusblendZeit > :Jetzt2 ) ');
      q.SQL.Add(' ORDER BY Termine.Von;');

      q.Parameters.ParamByName('Jetzt1').DataType := ftDateTime;
      q.Parameters.ParamByName('Jetzt1').Value := _Jetzt;
      q.Parameters.ParamByName('Jetzt2').DataType := ftDateTime;
      q.Parameters.ParamByName('Jetzt2').Value := _Jetzt;
Dürfte jetzt auch nicht unbedingt schlechter wartbar sein oder unübersichtlicher.

Gut, wenn es eine Funktion oder Prozedur ist und T von außen kommt, dann ist
Delphi-Quellcode:
      q.SQL.Add(t);
      q.SQL.Add(' ORDER BY Termine.Von;');
schon ok.

Aber nichtsdestotrotz: Parameter erst befüllen, wenn das SQL fertig ist, dann gibt es keinen Grund für irgendeine Routine das SQL erneut zu parsen und dabei ggfls. eine andere Entscheidung bezüglich der Parametertypen treffen zu sollen können müssen.

Olli73 24. Jan 2025 17:28

AW: TAdoQuery Parameters.DataType ändert sich nach SQL.Add
 
Setz mal "ParamCheck" der Query auf false, bevor du das "Order-By-SQL" anhängst ...


Alle Zeitangaben in WEZ +1. Es ist jetzt 19:15 Uhr.

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