2012-03-30 80 views
1

我有以下問題。我需要在存儲過程中過濾取數據:在Oracle中使用'IS IN'語句調用存儲過程

SELECT * FROM tab WHERE post_code IS IN ('pc1', 'pc2', 'pc3'); 

我的問題是:如何通過參數PC1,PC2,PC3 ...到存儲過程? 作爲一個數組或字符串? 當我嘗試作爲字符串傳遞我有撇號的問題。 在我看來傳球達陣是不好的,因爲表現......我將需要創建循環,並創建的字符串,像這樣被傳遞:

SELECT * FROM tab WHERE post_code IS IN (post_codes); 

如何做是正確的?

+2

:首先,'IS IN'是不正確的語法,使用'IN'而已,我看到二硝基甲苯任何函數調用在上面的查詢 – 2012-03-30 11:12:57

回答

2

不確定爲什麼您認爲傳遞數組會導致性能問題。

這將工作:

declare 
    post_codes sys.dbms_debug_vc2coll := new sys.dbms_debug_vc2coll ('pc1', 'pc2', 'pc3'); 
    lrec tab%rowtype; 
begin 
    select * into lrec 
    where post_code in (select * from table(post_codes)); 
end; 
/

這僅僅是概念證明。如果查詢返回多行,它將拋出TOO_MANY_ROWS異常。因爲你沒有提供任何你想要達成的目標,所以我沒有打算髮明任何東西。

0

最簡單的方式,在我看來是使用SQL分裂您的字符串:

with id_generator 
    as 
    (
     SELECT regexp_substr(:txt, '[^,]+', 1, LEVEL) token 
     FROM dual 
     CONNECT BY LEVEL <= length(:txt) - length(REPLACE(:txt, ',', '')) + 1 
    ) 
    select u.id, u.username 
    from users u, id_generator g 
    where u.id = g.token; 

這個查詢看起來有點嚇人,但你可以採取頂部並運行它孤立地看什麼它的作用:

SELECT regexp_substr(:txt, '[^,]+', 1, LEVEL) token 
FROM dual 
CONNECT BY LEVEL <= length(:txt) - length(REPLACE(:txt, ',', '')) + 1 

這在您的逗號分隔的列表,然後你就可以加入到其他表,讓您的結果產生每項一行。在我的博客上這個問題

更多的討論 - http://betteratoracle.com/posts/20-how-do-i-bind-a-variable-in-list

+0

Easieness取決於上下文。起點是一個字符串?或者,起點是一組離散值,隨後將它們連接在一起以嘗試將它們傳遞給查詢? – APC 2012-03-30 15:37:21