2013-04-05 26 views

Trả lời

6

Bạn cũng có thể sử dụng một cái gì đó như thế này:

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

Bạn sẽ phải tạo một thủ tục mới Firebird gọi là "GetIntegerList" mà sẽ giống như thế này:

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 

Lưu ý, điều này đã được thực hiện trong Firebird 2.5.2.

3

AFAIK no, thats not possible. Trong khi Firebird có loại dữ liệu mảng, hỗ trợ cho nó là thô sơ và sử dụng mảng thường không được khuyến cáo. Tôi nghĩ rằng giải pháp đơn giản nhất để vượt qua các mảng như (dấu phẩy tách ra) chuỗi và sau đó sử dụng câu lệnh for execute statement để có được những resultset, một cái gì đó giống như

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 

Điều này có nghĩa tuy nhiên rằng tuyên bố bạn sử dụng để có được kết quả cũng thay đổi, thay vì WHERE bạn sẽ sử dụng các tham số của thủ tục lưu trữ CITY:

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

Một lựa chọn khác để gửi danh sách tham số là sử dụng global temporary table. Điều này có pro mà bạn có thể gửi số lượng lớn các ID mà không vượt quá mức tối đa cho phép báo cáo kích thước nhưng nó là nhiều việc để thiết lập cuộc gọi ...

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

Tôi nghĩ nó hoạt động, nhưng tôi có hơn 10.000 thành phố trong cơ sở dữ liệu của mình. – dataol

+1

@dataol Bạn có muốn vượt qua tất cả? Tại sao không chỉ tham gia vào bảng chứa những thành phố này? –

+0

@MarkRotteveel Không phải tất cả, chỉ là các bản ghi đã chọn. Nhưng người dùng có thể chọn 1 hoặc 10.000 thành phố. – dataol

0

Hãy thử điều này:

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

Nếu bạn sử dụng Firebird 1.5 (Nó sẽ làm việc trên các phiên bản cao hơn quá), bạn có thể sử dụng chức năng đơn giản này tôi đã thực hiện để chuyển đổi một chuỗi duy nhất vào một mảng số nguyên:

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 

Cách sử dụng

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

Sẽ trả lại điều này:

INT_VALUE 
1 
2 
3 
4 
5 
200 
1 
598415 
2 
Các vấn đề liên quan