Delphi-PRAXiS
Seite 1 von 2  1 2      

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Datenbanken (https://www.delphipraxis.net/15-datenbanken/)
-   -   Delphi AdoQuery Parameterübergabe für SQL "IN" Operator (https://www.delphipraxis.net/73750-adoquery-parameteruebergabe-fuer-sql-operator.html)

glunzl 23. Jul 2006 14:51

Datenbank: Access • Version: 2000 • Zugriff über: ADO

AdoQuery Parameterübergabe für SQL "IN" Operator
 
Hallo!

Folgendes Problem quält mich schon eine Weile ... Ich möchte aus einer Tabele, die mehrere Störtexte enthält, einige anzeigen. Zu jedem Störtext gehört ein Gerätetyp (Typ Zahl), die der User einzeln auswählen kann. Um nicht eine überdimensionale ODER-Verknüpfung zu basteln, will ich den IN Operator benutzen.

Ich greife mit einer TADOQuery auf eine Access 2000 DB zu.
In Access sieht die Where Klausel wie folgt aus und funktioniert.

WHERE ((tblGer.gerTyk) In (13,15,16)))

In meinem Programm so:
Delphi-Quellcode:
Query1.SQL.Add('WHERE ((tblGer.gerTyk) In (:GTypes)))') ;
Query1.Parameters.ParamValues['GTypes'] := '15,16,13' ;
Wobei ich die Parameter jetzt reingeschrieben habe. Diese werden anhand von Checkboxen ermittelt. Nach Ausführern der Query bleibt die Datenmenge leer. Trage ich nur '15' oder 15 ein funktioniert es einwandfrei. Muss ich dem Parameter noch irgendwie sagen, das er ein Integer Wert ist?

Gruß
Michi

mkinzler 23. Jul 2006 15:50

Re: AdoQuery Parameterübergabe für SQL "IN" Operat
 
Versuch mal
Delphi-Quellcode:
Query1.SQL.Add('WHERE ((tblGer.gerTyk) In :GTypes))') ;
Query1.Parameters.ParamValues['GTypes'] := '(15,16,13)' ;

glunzl 23. Jul 2006 16:17

Re: AdoQuery Parameterübergabe für SQL "IN" Operat
 
Hallo!

Dann kommt eine Exception, das der IN Operator eine Klammer benötigt. Diese habe ich dann bei der Parameterübergabe mit eingebaut, leider ohne Erfolg.

Folgendes konnte ich noch feststellen: Bis 2 Werte, durch Komma getrennt, funktioniert das ganze, ab dem 3. nicht mehr!?! Liegt das vielleicht an dem Variant Typen des Parameters?

Gruß
Michi

marabu 23. Jul 2006 16:39

Re: AdoQuery Parameterübergabe für SQL "IN" Operat
 
Hallo Michi,

dein Problem ist eventuell, dass der Parser einen numerischen Wert erkennt. Versuche doch mal den Parameter vorher zu typisieren. Überprüfen kannst du den Erfolg bzw. Misserfolg durch eine Inspektion des Parameter-Typs vor dem Query.Open().

Grüße vom marabu

glunzl 23. Jul 2006 16:57

Re: AdoQuery Parameterübergabe für SQL "IN" Operat
 
Hallo maramu!

An eine Typüberprüfung habe ich auch schon gedacht. Nur finde ich keine passende Methode dafür.

Es müsste IMO ungefähr so aussehen:
Delphi-Quellcode:
Query1.Parameters.ParamValues['GTypes']. ...
Nur kommt mit dem Punkt hinter ['GTypes'] keine neue Auswahl ...

Gruß
Michi

glunzl 23. Jul 2006 17:08

Re: AdoQuery Parameterübergabe für SQL "IN" Operat
 
Vielleicht weiß jemand eine anderen Rat ...

Delphi-Quellcode:
  // Abfrage der Checkboxen:
  if CB.Checked then GTypes := GTypes + '15,' ;
  if BK.Checked then GTypes := GTypes + '13,' ;
  if LK.Checked then GTypes := GTypes + '14,' ;
  if AGV.Checked then GTypes := GTypes + '1,' ;
  if EAGV.Checked then GTypes := GTypes + '27,' ;
  if FB.Checked then GTypes := GTypes + '16,' ;
  if TT.Checked then GTypes := GTypes + '11,' ;
  if Chassis.Checked then GTypes := GTypes + '14,' ;
  if Gabelstapler.Checked then GTypes := GTypes + '17,' ;
  if ReachStacker.Checked then GTypes := GTypes + '20,' ;
  if Saeulen.Checked then GTypes := GTypes + '21,' ;
  if ZM.Checked then GTypes := GTypes + '22,' ;
  if Smart.Checked then GTypes := GTypes + '23,' ;

  Query1.Active := false ;
  Query1.SQL.Clear ;
  Query1.ParamCheck := true ;

  Query1.SQL.Add( ...)

  // where Klausel, Parameter
  Query1.SQL.Add('WHERE ((tblGer.gerTyk) In (:GTypes)))') ;

  // letztes Komma entfernen
  GTypes := LeftStr(GTypes, length(GTypes)-1) ;

  // Parameter übergeben
  Query1.Parameters.ParamValues['GTypes'] := GTypes ;

  Query1.Active := true ;
Vielleicht hat jemand eine anderen Lösungsansatz ...

Michi

marabu 23. Jul 2006 18:09

Re: AdoQuery Parameterübergabe für SQL "IN" Operat
 
Hallo Michi,

die vielen CheckBoxen würden mir zuviel Raum im GUI einnehmen - meine Wahl wäre eine CheckListBox, die Werte (ID, NAME) für die GTypes würde ich im Ereignis OnCreate() der Form aus der entsprechenden Tabelle der Datenbank einlesen, den Schlüssel als Object und den Namen als String. Später kann man dann die Schlüsselliste so bilden:

Delphi-Quellcode:
function ListOfKeys(clb: TListBox): String;
var
  i: Integer;
  s: TStrings;
begin
  s := TStringList.Create;
  with clb do
    for i := 0 to Pred(Count) do
      if Checked[i] then
        s.Add(IntToStr(Integer(Items.Objects[i])));
  s.QuoteChar := #0;
  Result := s.DelimitedText;
  s.Free;
end;
Noch ein paar Hinweise allgemeiner Natur: Vor einem nachfolgenden Schreibzugriff auf die Eigenschaft SQL brauchst du die Eigenschaft Active einer Query nicht auf False setzen - das wird implizit gemacht. ParamCheck brauchst du nur zur Entwurfszeit einmal zu setzen - diese Einstellung ändert sich bei dir ja nicht mehr. Klammern in der WHERE-Klausel sind nur nötig, wenn du mit den Vorrangregeln bei logischen Ausdrücken nicht einverstanden bist - in deinem Fall erschweren sie nur die Lesbarkeit.

Die Typisierung des Parameters kannst du so vornehmen:

Delphi-Quellcode:
with Query.Parameters.ParamByName('GTYPES') do
begin
  DataType := ftString;
  Value := '1,2,3,4,5,6,7'; // oder wie immer du deinen String übergeben willst
end;
Wenn das SELECT-Statement sich nie ändert - das ist das Ziel der Parameterverwendung - dann muss auch die Eigenschaft SQL der Query nur einmal gesetzt werden, allerdings muss dann die Query explizit geschlossen und wieder geöffnet werden um die geänderten Parameterwerte zu berücksichtigen.

Getippt und nicht getestet.

marabu

rwachtel 24. Jul 2006 11:52

Re: AdoQuery Parameterübergabe für SQL "IN" Operat
 
Eine SELECT...IN-Abfrage lässt sich schlicht und ergreifend nicht parametrisieren.

marabu 24. Jul 2006 12:17

Re: AdoQuery Parameterübergabe für SQL "IN" Operat
 
Hallo Robert,

die pauschale Aussage ist nicht korrekt, die Parametrisierung mit einem einzelnen Wert (Trivialfall) ist definitiv möglich, nur mit einer Werteliste scheint sich der interne Code zur Aufbereitung der SQL communication area etwas zu verschlucken. Offensichtlich ist ftString als Datentyp für den Parameter nicht der richtige Weg. Als Zwischenlösung könnte man die "Parametrisierung" über einen FormatString abwickeln.

Grüße vom marabu

rwachtel 24. Jul 2006 12:35

Re: AdoQuery Parameterübergabe für SQL "IN" Operat
 
Hallo marabu!

Zitat:

Zitat von marabu
[...] die pauschale Aussage ist nicht korrekt, die Parametrisierung mit einem einzelnen Wert (Trivialfall) ist definitiv möglich, [...]

Stimmt, diesen Fall habe ich gerade mal nicht bedacht. Die Frage stellt sich nach dem Sinn einer solchen Abfrage :wink:

Zitat:

[...] nur mit einer Werteliste scheint sich der interne Code zur Aufbereitung der SQL communication area etwas zu verschlucken. Offensichtlich ist ftString als Datentyp für den Parameter nicht der richtige Weg. Als Zwischenlösung könnte man die "Parametrisierung" über einen FormatString abwickeln.
Ja, Parameter müssen vom Typ TDataType sein. Daher ist kein Listentyp möglich.

Eine "Parametrisierung" über einen FormatString o.ä. wäre ein gangbarer Workaround. Man verliert halt je nach verwendetem RDBMS und Datenzugriffsschicht die eventuellen Vorteile einer parametrisierten Abfrage. Aber wir sprechen hier ja von Access... :mrgreen:

Ein andere Alternative wäre u.U. die Verwendung einer zweiten Tabelle à la

SQL-Code:
SELECT * FROM Tabelle WHERE Wert IN (SELECT Nachschlagewert FROM Tabelle2)
Allerdings habe ich keinen blassen Schimmer, ob Access sowas unterstützt.


Alle Zeitangaben in WEZ +1. Es ist jetzt 06:02 Uhr.
Seite 1 von 2  1 2      

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