2012-11-29 24 views
4

我想查詢一個數字列表到一個plsql變量中,並在另一個sql查詢中的in子句中使用它。我在下面創建了一個我想做的測試用例。在'IN'子句中使用綁定變量

我沒有谷歌的解決方案,我認爲這一定是可能的,但我只是沒有得到它運行。請幫助我編譯解決方案。使用

CREATE OR REPLACE PROCEDURE PROCEDURE1 
as 
    type t_id is table of number; 
    v_ids t_id; 
    v_user_ids number; 
BEGIN 

-- fill variable v_id with id's, user_id is of type number 
select user_id 
bulk collect into v_ids 
from user_users; 

-- then at a later stage ... issue a query using v_id in the in clause 
select user_id into v_user_ids from user_users 
-- this line does not compile (local collection type not allowed in SQL statements) 
where user_id in (v_ids); 

END PROCEDURE1; 
+1

也許這是一個簡化的演示,但在你提供的情況下,你不只是將兩個查詢合併爲一個? 「Select ... from ... where user_id in(select user_id from ...)」?或者執行加入? –

+0

是的,這是愚蠢的,可能沒有意義。我需要編譯的例子 - 我得到一個錯誤的行:其中user_id在(v_ids) – opi

+0

正在使用一個SQL數組與plsql嵌套表不是你的選擇?如果是這樣,我們可以使用TABLE()函數來解決這個問題(儘管你的最後一個語句沒有意義,因爲它是一個select into,所以你最後只有一行?如果你真正的sql是select max ()或rownum = 1或其他)。 – DazzaL

回答

4

一個SQL類型:

SQL> create type t_id is table of number; 
    2/

Type created. 

SQL> CREATE OR REPLACE PROCEDURE PROCEDURE1 
    2 as 
    3 v_ids t_id; 
    4 v_user_ids number; 
    5 BEGIN 
    6 
    7 -- fill variable v_id with id's, user_id is of type number 
    8 select user_id 
    9 bulk collect into v_ids 
10 from user_users 
11 where user_id between 100 and 120; 
12 
13 select user_id into v_user_ids 
14  from user_users 
15  where user_id in (select /*+ cardinality(t, 10) */ t.column_value from table(v_ids) t) 
16  and rownum = 1; 
17 
18 dbms_output.put_line(v_user_ids); 
19 
20 END PROCEDURE1; 
21/

Procedure created. 

SQL> exec procedure1 
100 

其中cardinality(t, 10)應該是多少元素數組中一個合理的猜測。

注: 使用無界批量收集像你這樣:

8 select user_id 
    9 bulk collect into v_ids 
10 from user_users; 

一般不是很大,如果你的陣列可以用幾千或更多的行結束了,因爲你把太多的壓力在內存並最終會崩潰代碼。用明確的光標open x for ..和帶有限制條款(即fetch x bulk collect into v_ids limit 100)的循環批量提取並且批量處理比如說100-1000可以更好地滿足您的要求。

+0

偉大的這個作品的內部選擇伎倆!我可以避免「創建類型...」嗎?是否有可能重用已由oracle提供的類型? - 真正的代碼確實經歷了1000批次中的數百萬條記錄。我是java傢伙,出於性能原因需要在plsql中執行此操作。 – opi

+0

你可以查看你的數據庫中有什麼可用選擇所有者,type_name,coll_type,upper_bound,precision,來自all_coll_types的scale,其中elem_type_name ='NUMBER';'並選擇一個(例如'v_ids KU $ _OBJNUMSET;')。請記住,通過使用Oracle擁有的(SYS),其主題將在未來的Oracle版本中消失或更改:) – DazzaL

+0

「批量1,000」和「性能」聲音對我來說是互斥的。如果您確實有大量記錄,那麼請考慮將您需要傳遞給代碼的值插入到全局臨時表中並使用盡可能少的SQL語句加入到它中。 –