Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Datenbanken (https://www.delphipraxis.net/15-datenbanken/)
-   -   Delphi ADO Query Parameter zur Laufzeit erstellen (https://www.delphipraxis.net/200284-ado-query-parameter-zur-laufzeit-erstellen.html)

Thaleilama 6. Apr 2019 12:21

Datenbank: MySQL • Version: 10.1.37 • Zugriff über: ODBC

ADO Query Parameter zur Laufzeit erstellen
 
Hallo zusammen!

Ich bin gerade etwas am Verzweifeln bei dem Versuch Parameter für eine ADOQuery zur Laufzeit zu erstellen.
Ich nutzte Delphi 10.2.

Das ERP-System sowie die App sind über ODBC angelegt.

Die Beispiele sind etwas gekürzt und auf die wesentlichen Funktionen beschränkt.

Ich habe mir eine Datenbank Unit erstellt und ein TDatabse Klasser erstellt, die von der TADOConnection erbt.
Das gleiche mit einer TQuery Klasse, die von der TADOQuery erbt.


Code:
  TDatabase = class(TADOConnection)
    constructor Create; reintroduce;
  private

  public
    function TryEstablishingConnection: Boolean;

    procedure SetConnectionToERP;
    procedure SetConnectionToApp;
  end;

  TQuery = class(TADOQuery)
    constructor Create; reintroduce;
  private

  public

  end;
Die Konstruktoren sind wie folgt

Code:
  constructor TDatabase.Create;
  begin
    inherited Create(nil);
    Self.LoginPrompt := False;
    Self.Mode       := cmReadWrite;
  end;

  constructor TQuery.Create;
  begin
    inherited Create(nil);
    Self.EnableBCD := False;
  end;
Dann gibt es noch eine Unit für Einstellungen, die die Einstellungen in der MySQL-Datenbank setzten soll.
Die Funktion dafür lautet wie folgt

Code:
  class procedure TEinstellung.SetzeTransferZeitpunkt(Nummer: Integer);
  var
    appCon:   TDatabase;
    appUpdate: TQuery;
  begin
    appCon := TDatabase.Create;
    appCon.SetConnectionToApp;

    if appCon.TryEstablishingConnection then
    begin
      appUpdate := TQuery.Create;
      appUpdate.Connection := appCon;

      appUpdate.SQL.Text := 'UPDATE appeinstellungen SET zeit = CURRENT_TIMESTAMP WHERE nummer = :appNummer';
      appUpdate.Parameters.ParamByName('appNummer').Value := Nummer;

      try
        appUpdate.ExecSQL;
      except
        on E: Exception do
        begin
          appUpdate.Close;
        end;
      end;

      appUpdate.Close;
      FreeAndNiL(appUpdate);
    end;

    appCon.CloseConnection;
    FreeAndNil(appCon);
  end;
Debugge ich diese Anwendung koommt an der appUpdate.SQL.Text Zeile folgende Fehlermeldung
Die Argumente sind vom falschen Typ, liegen außerhalb des Gültigkeitsbereiches oder sind miteinander unvereinbar

Daraufhin habe ich die TQuery Klasse erweitert und den Aufruf bei den Einstellungen angepasst

Code:
  TQuery = class(TADOQuery)
    constructor Create; reintroduce;
  private

  public
    procedure AddIntegerParam(FieldName: String);
  end;

  procedure TQuery.AddIntegerParam(FieldName: string);
  begin
    Parameters.AddParameter.Name := FieldName;
    Parameters.ParamByName(FieldName).DataType := ftInteger;
  end;


[Einstellungen]
[...]
  appUpdate.AddIntegerParam('appNummer');
  appUpdate.SQL.Text := 'UPDATE appeinstellungen SET zeit = CURRENT_TIMESTAMP WHERE nummer = :appNummer';
  appUpdate.Parameters.ParamByName('appNummer').Value := Nummer;
[...]
Der Fehler blieb jedoch bestehen. Ich habe auch versucht appUpdate.Prepared := True; bzw. appUpdate.Prepared := False; vor dem setzten des SQL.Textes auszuführen.
Ohne eine Änderung.
Nach einigem Suchen fand ich dann eine Funktion um Parameter mittels CreateParameter zu erzeugen und habe das in die AddIntegerParam Prozedur eingebaut.

Code:
  procedure TQuery.AddIntegerParam(FieldName: string; Value: Integer);
  begin
    Parameters.CreateParameter(FieldName, ftInteger, pdInputOutput, -1, Value);
  end;
Der Fehler bliebt jedoch weiterhin bestehen. Nach weiterem Suchen fand ich dann heraus, dass es manchmal Probleme geben kann und ich den Parameter in der Query in "" setzen soll.
Dies habe ich entsprechend umgebaut zu

Code:
  appUpdate.AddIntegerParam('appNummer');
  appUpdate.SQL.Text := 'UPDATE appeinstellungen SET zeit = CURRENT_TIMESTAMP WHERE nummer = ":appNummer"';
  appUpdate.Parameters.ParamByName('appNummer').Value := Nummer;
Dann sprang der Debugger weiter bis zur Zeile nach dem setzen des SQL.Text.
Hier erscheint nun die Fehlermeldung: Parameter appNummer nicht gefunden.
Daher habe ich den Block erweitert, damit der SQL.Text nochmal geparst wird

Code:
  appUpdate.AddIntegerParam('appNummer');
  appUpdate.SQL.Text := 'UPDATE appeinstellungen SET zeit = CURRENT_TIMESTAMP WHERE nummer = ":appNummer"';
  appUpdate.Parameters.ParseSQL(appUpdate.SQL.Text, True);
  appUpdate.Parameters.ParamByName('appNummer').Value := Nummer;
Dies brachte allerdings auch keinen Erfolg, der Parameter kann noch immer nicht gefunden werden.

Hat noch jemand eine Idee was ich hier Probieren könnte?

Thaleilama 6. Apr 2019 16:12

AW: ADO Query Parameter zur Laufzeit erstellen
 
Zum Testen habe ich das ganze mal in eine Formularanwenung verlegt. Dort war das selbe Problem.

Ich habe dann aufgehört die Query zur Laufzeit zu erzeugen und auf das Formular gelegt.

Code:
  appUpdate.SQL.Text := 'UPDATE appeinstellungen SET zeit = CURRENT_TIMESTAMP WHERE nummer = :appNummer';
  appUpdate.Parameters.ParamByName('appNummer').Value := Nummer;
Der Fehler Die Argumente sind vom falschen Typ, liegen außerhalb des Gültigkeitsbereiches oder sind miteinander unvereinbar bestand jedoch weiterhin.

Dann habe ich auf dem Formular in der Query Komponente den Parameter von Hand eingetragen, den Wert weiterhin im Quellcode zugewiesen.
Der Fehler bestand weiterhin.

Er verschwand erst, nachdem ich den Query.Text nicht im Quellcode setzte sondern direkt über den Objektinspektor der TADOQuery Komponente.
Das Value wird weiterhin zur Laufzeit gesetzt.

Es funktioniert nun, allerdings ist es etwas umständlich für jede einzelne Query eine eigene Komponente anzulegen.

Delphi.Narium 6. Apr 2019 17:36

AW: ADO Query Parameter zur Laufzeit erstellen
 
Bei den ADOs nutze ich immer Parameter. Die SQLs werden zur Laufzeit erstellt bzw. aus Konstanten übernommen. Das funktioniert problemlos, genauso, wie Du es ursprünglich vorhattest.

Parameter im SQL darf man aber nicht in "" setzen. Innerhalb der "" wird ein Parameter nicht mehr als solcher erkannt. Er wird dann zum Inhalt einer Stringkonstanten.

Die Fehlermeldung Die Argumente sind vom falschen Typ, liegen außerhalb des Gültigkeitsbereiches oder sind miteinander unvereinbar ist eher ein Hinweis auf datenbankseitige Probleme, als auf Implementierungsfehler.

Mir scheint, das die Nummer aus der Datenbank nicht typkompatibel zur Nummer aus Delphi ist.

Von welchem Typ ist die Datenbankspalte Nummer?
Von welchem Typ ist die Delphivariabel Nummer?

Thaleilama 6. Apr 2019 19:02

AW: ADO Query Parameter zur Laufzeit erstellen
 
Der Wert der Variablen ist ein Integer, in der Prozedur wurde der Datentyp auf ftInteger gestellt.

Mit der ersten Methode so
Code:
  procedure TQuery.AddIntegerParam(FieldName: string);
  begin
    Parameters.AddParameter.Name := FieldName;
    Parameters.ParamByName(FieldName).DataType := ftInteger;
  end;
und mit der zweiten so

Code:
  procedure TQuery.AddIntegerParam(FieldName: string; Value: Integer);
  begin
    Parameters.CreateParameter(FieldName, ftInteger, pdInputOutput, -1, Value);
  end;
In der Komponente auf dem Formular ist genau das gleiche eingestellt, nur nicht von mir zur Laufzeit erstellt worden. Da klappt es problemlos.
Die Spalte in der Datenbank ist ebenfalls Integer. Hier der CREATE-Code

Code:
  `nummer` INT(11) NOT NULL,

Bernhard Geyer 6. Apr 2019 19:27

AW: ADO Query Parameter zur Laufzeit erstellen
 
Mittels ADO-Komponenten über ODBC auf eine MySQL-Datenbank zugreifen.
Das ist m.E. das schlechteste was man machen kann. AFAIK musst du *irgendwelche* Einstellungen (ich glaub im ODBC-Treiber) vornehmen damit es halbwegs funktioniert.

Genaueres kann nicht sagen, da wir ein paar € ausgeben um mit den Zugriff keinerlei Probleme zu haben -> https://www.devart.com/dac.html

Übrigens: Damit umgeht man auch die GPL-Falle von MySQL. So wie du zugreifst müssen deine Kunden, wenn du den Quellcode nicht offen legst MySQL-Lizenzen kaufen!


Alle Zeitangaben in WEZ +1. Es ist jetzt 15:59 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