Parameter in Abfrage mit In-Klausel?

Ich möchte Parameter für die Abfrage wie folgt verwenden:

SELECT * FROM MATABLE WHERE MT_ID IN (368134, 181956) 

also denke ich darüber nach

 SELECT * FROM MATABLE WHERE MT_ID IN (:MYPARAM) 

aber es funktioniert nicht …

Gibt es eine Möglichkeit, dies zu tun?

Ich benutze tatsächlich IBX und Firebird 2.1

Ich weiß nicht, wie viele Parameter in IN-Klausel.

Ich benutzte eine globale temporäre Tabelle in Firebird, die Parameterwerte zuerst einfügt und Ergebnisse abruft, die ich einen regulären JOIN statt einer WHERE ... IN Klausel verwende. Die temporäre Tabelle ist transaktionsspezifisch und wird beim ON COMMIT DELETE ROWS gelöscht ( ON COMMIT DELETE ROWS ).

Für wen ist immer noch interessiert. Ich habe es in Firebird 2.5 mit einer anderen gespeicherten Prozedur getan, die von diesem Beitrag inspiriert wurde.

Wie man Komma getrennte characterkette innerhalb der gespeicherten Prozedur aufspaltet?

 CREATE OR ALTER PROCEDURE SPLIT_STRING ( ainput varchar(8192)) RETURNS ( result varchar(255)) AS DECLARE variable lastpos integer; DECLARE variable nextpos integer; DECLARE variable tempstr varchar(8192); BEGIN AINPUT = :AINPUT || ','; LASTPOS = 1; NEXTPOS = position(',', :AINPUT, LASTPOS); WHILE (:NEXTPOS > 1) do BEGIN TEMPSTR = substring(:AINPUT from :LASTPOS for :NEXTPOS - :LASTPOS); RESULT = :TEMPSTR; LASTPOS = :NEXTPOS + 1; NEXTPOS = position(',', :AINPUT, LASTPOS); suspend; END END 

Wenn Sie den SP die folgende list übergeben

KommaSepariertelist = 1,2,3,4

und Ruf an

 SELECT * FROM SPLIT_STRING(:CommaSeperatedList) 

das Ergebnis wird sein:

 RESULT 1 2 3 4 

Und kann wie folgt verwendet werden:

 SELECT * FROM MyTable where MyKeyField in ( SELECT * FROM SPLIT_STRING(:CommaSeperatedList) ) 

Vielleicht solltest du es so sagen:

 SELECT * FROM MATABLE WHERE MT_ID IN (:MYPARAM1 , :MYPARAM2) 

Ich denke nicht, dass es etwas ist, das getan werden kann. Gibt es einen bestimmten Grund, warum Sie die Abfrage nicht selbst erstellen möchten?

Ich habe diese Methode ein paar Mal verwendet, es verwendet jedoch keine Parameter. Es verwendet eine Stringliste und seine Eigenschaft DelimitedText. Sie erstellen eine IDList und füllen sie mit Ihren IDs auf.

 Query.SQL.Add(Format('MT_ID IN (%s)', [IDList.DelimitedText])); 

Vielleicht möchten Sie auch Folgendes lesen:
http://www.sommarskog.se/dynamic_sql.html
und
http://www.sommarskog.se/arrays-in-sql-2005.html

Deckt dynamisches sql mit 'in' Klauseln und allen Arten ab. Sehr interessant.

Parameter sind Platzhalter für einzelne Werte. Das bedeutet, dass eine IN-Klausel, die eine durch Kommas getrennte list von Werten akzeptiert, nicht mit Parametern verwendet werden kann.

Denken Sie so: Wo immer ich einen Wert anlege, kann ich einen Parameter verwenden.

Also, in einer Klausel wie: IN (: param)

Ich kann die Variable an einen Wert binden, aber nur 1 Wert, zB: IN (4)

Wenn Sie nun einen "IN-Klausel-Wertausdruck" betrachten, get eine Reihe von Werten: IN (1, 4, 6) -> das sind 3 Werte mit Kommata zwischen ihnen. Das ist Teil der SQL-characterfolge, nicht Teil eines Werts, weshalb es nicht an einen Parameter gebunden werden kann.

Natürlich ist das nicht das, was Sie wollen, aber es ist das einzige, was mit Parametern möglich ist.

Die Antwort von Yurish ist eine Lösung in zwei von drei Fällen:

  • wenn Sie eine begrenzte Anzahl von Elementen haben, die zu Ihrer IN-Klausel hinzugefügt werden sollen
  • oder wenn Sie bereit sind, Parameter für jedes benötigte Element zu erstellen (Sie kennen die Anzahl der Elemente in der Entwurfszeit nicht)

Wenn Sie jedoch eine beliebige Anzahl von Elementen und manchmal überhaupt keine Elemente haben möchten, können Sie eine SLQ-statement im laufenden Betrieb generieren. Die Verwendung von Format hilft.

SELECT * FROM MATABLE WHERE MT_ID IN (: MYPARAM) anstelle von MYPARAM mit : verwenden Sie den Parameternamen.

wie SELECT * FROM MATABLE WO MT_ID IN (SELECT REGEXP_SUBSTR (** MYPARAM , '[^,] +', 1, LEVEL) VON DUAL CONNECT VON REGEXP_SUBSTR ( MYPARAM , '[^,] +', 1, LEVEL) ist nicht NULL))**

MYPARAM- '368134,181956'

Wenn Sie Oracle verwenden, sollten Sie Tomy Kytes Blogpost genau zu diesem Thema ( Link ) besuchen .

Nach Herrn Kytes Führung folgt hier ein Beispiel:

 SELECT * FROM MATABLE WHERE MT_ID IN (SELECT TRIM(substr(text, instr(text, sep, 1, LEVEL) + 1, instr(text, sep, 1, LEVEL + 1) - instr(text, sep, 1, LEVEL) - 1)) AS token FROM (SELECT sep, sep || :myparam || sep AS text FROM (SELECT ',' AS sep FROM dual)) CONNECT BY LEVEL <= length(text) - length(REPLACE(text, sep, '')) - 1) 

Wo würdest du binden :MYPARAM zu '368134,181956' in deinem Fall.

Hier ist eine Technik, die ich in der Vergangenheit benutzt habe, um dieses IN-Statement-Problem zu umgehen. Es erstellt eine OR-list basierend auf der Anzahl der Werte, die mit Parametern angegeben werden (einmalig). Dann musste ich nur die Parameter in der Reihenfolge hinzufügen, in der sie in der angegebenen Werteliste erschienen.

 var FilterValues: TStringList; i: Integer; FilterList: String; Values: String; FieldName: String; begin Query.SQL.Text := 'SELECT * FROM table WHERE '; // set base sql FieldName := 'some_id'; // field to filter on Values := '1,4,97'; // list of supplied values in delimited format FilterList := ''; FilterValues := TStringList.Create; // will get the supplied values so we can loop try FilterValues.CommaText := Values; for i := 0 to FilterValues.Count - 1 do begin if FilterList = '' then FilterList := Format('%s=:param%u', [FieldName, i]) // build the filter list else FilterList := Format('%s OR %s=:param%u', [FilterList, FieldName, i]); // and an OR end; Query.SQL.Text := Query.SQL.Text + FilterList; // append the OR list to the base sql // ShowMessage(FilterList); // see what the list looks like. if Query.ParamCount <> FilterValues.Count then raise Exception.Create('Param count and Value count differs.'); // check to make sure the supplied values have parameters built for them for i := 0 to FilterValues.Count - 1 do begin Query.Params[i].Value := FilterValues[i]; // now add the values end; Query.Open; finally FilterValues.Free; end; 

Hoffe das hilft.

Es gibt einen Trick, um umgekehrte SQL LIKE Bedingung zu verwenden.

Sie übergeben die list als characterfolge ( VARCHAR ) Parameter wie '~12~23~46~567~'

Dann haben Sie eine Abfrage wie where ... :List_Param LIKE ('%~' || CAST( NumField AS VARCHAR(20)) || '~%')

 CREATE PROCEDURE TRY_LIST (PARAM_LIST VARCHAR(255)) RETURNS (FIELD1....) AS BEGIN /* Check if :PARAM_LIST begins with colon "," and ands with colon "," the list should look like this --> eg. **",1,3,4,66,778,33,"** if the format of list is right then GO if not just add then colons */ IF (NOT SUBSTRING(:PARAM_LIST FROM 1 FOR 1)=',') THEN PARAM_LIST=','||PARAM_LIST; IF (NOT SUBSTRING(:PARAM_LIST FROM CHAR_LENGTH(:PARAM_LIST) FOR 1)=',') THEN PARAM_LIST=PARAM_LIST||','; /* Now you are shure thet :PARAM_LIST format is correct */ / * NOW ! */ FOR SELECT * FROM MY_TABLE WHERE POSITION(','||MY_FIELD||',' in :PARAM_LIST)>0 INTO :FIELD1, :FIELD2 etc... DO BEGIN SUSPEND; END END How to use it. SELECT * FROM TRY_LIST('3,4,544,87,66,23') or SELECT * FROM TRY_LIST(',3,4,544,87,66,23,') if the list have to be longer then 255 characters then just change the part of header f.eg. like PARAM_LIST VARCHAR(4000)