2013-04-05 2 views

Antwort

6

Sie auch so etwas wie diese verwenden:

SELECT * 
FROM CITY 
WHERE ID_CITY IN (SELECT ID FROM GetIntegerList('1, 2, 12, 45, 75, 45')) 

Sie müssten einen neuen Firebird Verfahren schaffen, genannt „GetIntegerList“, die wie folgt aussehen würde:

CREATE OR ALTER PROCEDURE "GETINTEGERLIST"("AINTEGERLIST" VARCHAR(32000)) 
returns (
    ID integer 
) 
as 
    declare variable IntegerList varchar(32000); 
    declare variable CommaPos integer; 
    declare variable IntegerVal varchar(10); 
begin 
    IntegerList = AIntegerList || ' '; 
    CommaPos = Position(',', IntegerList); 

    while (CommaPos > 0) do 
    begin 
    IntegerVal = Trim(SubString(IntegerList from 1 for CommaPos - 1)); 

    if (Char_Length(IntegerVal) > 0) then 
    begin 
     if (IntegerVal similar to '[0-9]*') then 
     begin 
     ID = Cast(IntegerVal as integer); 
     suspend; 
     end 
    end 

    if (Char_Length(IntegerList) > CommaPos) then 
     IntegerList = SubString(IntegerList from CommaPos + 1); 
    else 
     IntegerList = ''; 

    CommaPos = Position(',', IntegerList); 
    end 

    IntegerList = Trim(IntegerList); 

    if (Char_Length(IntegerList) > 0) then 
    begin 
    if (IntegerList similar to '[0-9]*') then 
    begin 
     ID = Cast(IntegerList as integer); 
     suspend; 
    end 
    end 
end 

Hinweis, diese in Firebird 2.5.2 durchgeführt wurde.

3

AFAIK nein, das ist nicht möglich. Während Firebird Array-Datentyp hat, ist die Unterstützung dafür rudimentär und die Verwendung von Arrays wird im Allgemeinen nicht empfohlen. Ich denke, die einfachste Lösung wäre, das Array als (durch Komma getrennt) Zeichenfolge übergibt und dann verwenden, um die for execute statement Anweisung, um das Suchresultates zu bekommen, so etwas wie

create procedure CITY (INPUT_LIST_ID varchar(1024)) 
returns(...) 
as 
begin 
    for execute statement 
    'select ... from T where ID_CITY IN ('|| INPUT_LIST_ID ||')' into ... 
    do begin 
    suspend; 
    end 
end 

Dies bedeutet jedoch, dass die Aussage, die Sie das Ergebnis zu erhalten verwenden, um auch Änderungen, statt WHERE würden Sie die Parameter der gespeicherten Prozedur verwenden CITY:

SELECT * FROM CITY('1, 2, 12, 45, 75, 45') 

Eine weitere Möglichkeit der Parameterliste zu senden ist global temporary table zu verwenden. Dies hat den Profi, die Sie sehr große Anzahl von IDs ohne Überschreitung der maximal zulässigen Größe Aussagen senden können, aber es ist mehr Arbeit, um die Verbindung aufzubauen ...

create global temporary table SP_CITY_PARAMS (
    id int not null primary key 
) 
on commit delete rows; 

create procedure CITY 
returns(...) 
as 
begin 
    for select ... from T where ID_CITY IN (
     select id from SP_CITY_PARAMS 
) into ... 
    do begin 
    suspend; 
    end 
end 
+0

Ich denke, es funktioniert, aber ich habe mehr als 10.000 Städte in meiner Datenbank. – dataol

+1

@dataol Möchten Sie alle weitergeben? Warum nicht einfach auf den Tisch mit diesen Städten gehen? –

+0

@MarkRotteveel Nicht alle, nur die ausgewählten Datensätze. Aber ein Benutzer kann 1 oder 10.000 Städte auswählen. – dataol

0

Versuchen Sie folgendes:

SELECT * 
    FROM CITY 
    WHERE '/city1/city2/city.../' containing '/' || ID_CITY || '/'; 
0

Wenn Sie Firebird verwenden 1.5 (Es sollte höhere Versionen arbeiten auch), können Sie diese einfache Funktion i einen einzelnen String in ein Integer-Array zu konvertieren:

create or alter procedure INTEGER_LIST (
    input varchar(4096)) 
returns (
    INT_VALUE integer) 
as 
declare variable CHAR_COUNT integer; 
declare variable PARAM_LENGTH integer; 
declare variable READ_VALUE char(1); 
declare variable CURRENT_INTEGER varchar(20); 
begin 
    param_length = strlen(input); 
    char_count = 0; 
    current_integer = ''; 
    while (char_count < param_length) do begin 
     char_count = :char_count + 1; 
     read_value = substr(:input, :char_count, :char_count); 
     if (:read_value <> ',') then begin 
      current_integer = :current_integer || :read_value; 
     end else if (:read_value <> ' ') then begin 
      int_value = cast(:current_integer as integer); 
      current_integer = ''; 
      suspend; 
     end 

     if (:char_count = :param_length) then begin 
      int_value = cast(:current_integer as integer); 
      suspend; 
     end 
    end 
end 

Nutzungs

select int_value from integer_list('1,2,3,4, 5, 200, 1, 598415, 2')

Wird dies zurück:

INT_VALUE 
1 
2 
3 
4 
5 
200 
1 
598415 
2