2012-12-05 63 views
0

我在一個小菜一碟。我有一個接受參數並返回查​​詢結果的存儲過程。該查詢使用IN語句。將一個數組作爲參數傳遞到Oracle存儲過程

這裏是SP的結構:

CREATE OR REPLACE 
PROCEDURE EXAMPLE_SP 
(
    arg VARCHAR2, 
    argRS1 OUT cursors.rs 
) 
AS 
l_test VARCHAR2(255) := arg; 

BEGIN 

    OPEN argRS1 FOR 
    SELECT * FROM TABLE1 
    WHERE LOCATION IN (l_test); 

END EXAMPLE_SP; 

值的報表中的數字是可變的。 IN的選項來自UI側的選定表單複選框。

我使用PHP來檢索選​​定的複選框值。我已經嘗試將值內嵌入逗號分隔的字符串中。

我該邏輯是,查詢會再看看這樣的:

l_test = 'val1, val2, val3'; 
SELECT * FROM TABLE1 
WHERE LOCATION IN (val1, val2, val3); 

但沒有奏效。我不知道如何繼續。預先感謝任何建設性意見或建議。

回答

0

您可以添加這個逗號分隔的輸入參數爲VARCHAR()和使用以下WHERE語句:

where (','||l_test||',' like '%,'||LOCATION||',%') 

例如,如果l_test='2,3,4,5'LOCATION=3我們得到:

where (',2,3,4,5,' like '%,3,%') 

而且這是真的,如果LOCATION值在此列表中。

0

我認爲你所選擇的位置是VARCHAR,所以你需要轉換列表如下圖所示

l_test = '''val1''||','|| ''val2''||','||''val3'''; 

使您最終的查詢看起來像

SELECT * FROM TABLE1 
WHERE LOCATION IN ('val1', 'val2', 'val3'); 

你可以做這樣也

CREATE OR REPLACE 
PROCEDURE EXAMPLE_SP 
(
    arg VARCHAR2, 
    argRS1 OUT cursors.rs 
) 
AS 
l_test VARCHAR2(255) := arg; 

BEGIN 
    l_test:=''''||replace(l_test,',',''',''')||''''; 
    OPEN argRS1 FOR 
    SELECT * FROM TABLE1 
    WHERE LOCATION IN (l_test); 

END EXAMPLE_SP; 

:我沒有測試過這個,但我認爲這樣你就可以實現你想要的

0

我會這樣做,而不使用字符串操作。從理論上講,SQL注入的風險可能很小,因爲您使用的是複選框,所以最好在開始時實施良好的實踐,所以如果發生任何變化,就不要讓自己處於危險之中。

第二個好處是,您仍然可以使用您欄中的任何索引,如果您使用like '%...,則無法使用這些索引。

要做到這一點,你可以利用表函數和外部對象來填充你的「列表」。

作爲一個例子,我將從USER_OBJECTS返回OBJECT_NAME。

如果我創建兩個表:

create table tmp_test (a number); 
create table tmp_test2 (a number); 

和對象來保存表的列表,或在您的情況下的位置。

create type t_test_object is table of varchar2(30); 

接下來,這裏是您的程序的等價物。這是一個返回SYS_REFCURSOR的函數。它接受T_TEST_OBJECT作爲參數,這意味着首先需要在傳遞給函數之前填充。

create or replace function select_many (
     Ptest_object in t_test_object 
     ) return sys_refcursor is 

    l_curs sys_refcursor; 

begin 

    open l_curs for 
    select object_name 
     from user_objects 
    where object_name in (select * 
           from table(Ptest_object) 
            ); 

    return l_curs; 

end; 

最後,這裏是一個如何使用這個設置的例子。注意T_TEST_OBJECT的一個實例是如何填充多個值的。這個對象然後傳遞給函數返回你的光標。最後,顯示通過光標循環的值。顯然你可能想要使用遊標並以不同的方式填充TYPE。

SQL> declare 
    2 
    3  l_nested_table t_test_object := new t_test_object(); 
    4  l_cursor sys_refcursor; 
    5  -- Used for display demonstration only. 
    6  l_object_name user_objects.object_name%type; 
    7 
    8 begin 
    9 
10  l_nested_table.extend; 
11  l_nested_table(l_nested_table.last) := 'TMP_TEST'; 
12  l_nested_table.extend; 
13  l_nested_table(l_nested_table.last) := 'TMP_TEST2'; 
14 
15  l_cursor := select_many(l_nested_table); 
16  
17  loop -- Display example, not really relevant 
18  fetch l_cursor into l_object_name; 
19  exit when l_cursor%notfound; 
20  dbms_output.put_line(l_object_name); 
21  end loop; 
22 
23 end; 
24/
TMP_TEST 
TMP_TEST2 

PL/SQL procedure successfully completed. 
0

您可以使用Oracle實例從Oracle文檔:http://docs.oracle.com/cd/B28359_01/win.111/b28378/basfeat.htm#sthref207

看吧 - 返回表: Can an SQL procedure return a table?

這裏是另一個例子:

PACKAGE emp_actions IS 
    TYPE EnameTabTyp IS TABLE OF emp.ename%TYPE INDEX BY BINARY_INTEGER; 
    TYPE SalTabTyp IS TABLE OF emp.sal%TYPE INDEX BY BINARY_INTEGER; 
    ... 
    PROCEDURE hire_batch (ename_tab IN EnameTabTyp, sal_tab IN SalTabTyp, ...); 
    PROCEDURE log_names (ename_tab IN EnameTabTyp); 
END emp_actions; 
相關問題