2012-07-03 60 views
2

在傳遞參數時執行此代碼塊時出現問題。參數 rf是要輸入到WHERE子句中的變量的列表。要輸入的變量數量不是靜態的。在PL/SQL中將多個變量傳遞到WHERE條件存儲過程

create or replace 
procedure test_pl(rf in varchar2) 
IS 
counter number; 

BEGIN 
    select count(*) into counter from test_pl_imp where column_name in (rf); 
    dbms_output.put_line(counter); 
END; 

執行代碼如下:

declare 
inparam varchar2(20) := 'xyz,ran,dom'; 
begin 
goku.test_pl(inparam); 
end; 
/

我要像執行的WHERE條件:

where column_name in ('xyz','ran','dom'); 

但它被執行考慮xyz,ran,dom作爲字符串本身。

有沒有辦法實現它?

回答

5

您既可以將字符串分解出來,也可以使用INSTR最簡單的方法。

rf := ',' || rf || ','; 

SELECT 
    COUNT(*) 
INTO 
    counter 
FROM 
    test_pl_imp 
WHERE 
    INSTR(rf, ',' || column_name || ',') > 0; 

如果你有略微重新設計這個選項,我認爲這將是一個更清潔的設計採取一個字符串數組,而你是澆注到一個表,這樣就可以加入到test_pl_imp。

這可以做如下:

DECLARE 
    l_array goku.t_type := goku.t_type(); 
BEGIN 
    l_array.extend(3); 
    l_array(1) := 'xzy'; 
    l_array(2) := 'abc'; 
    l_array(2) := '123'; 

    goku.test_pl(l_array); 
END; 

然後你的包規範將包括既然你想公衆對上述呼叫的類型和程序如下:

CREATE OR REPLACE PACKAGE goku 
    TYPE r_type IS RECORD (
     search_term VARCHAR2 (30) 
    ); 

    TYPE t_type IS TABLE OF r_type; 

    PROCEDURE test_pl(l_array IN t_type); 
END goku; 

和你的包身體會像下面這樣:

CREATE OR REPLACE PACKAGE BODY goku 
    PROCEDURE test_pl(l_array IN t_type) IS 
     v_counter NUMBER; 
    BEGIN 

     SELECT 
      COUNT(tpi.*) 
     INTO 
      v_counter 
     FROM 
      test_pl_imp tpi 
      , TABLE(CAST(l_array as r_type)) la 
     WHERE 
      tpi.column_name = la.search_term; 

     DBMS_OUTPUT.PUT_LINE('Count :' || v_counter); 
    END; 
END goku; 
+3

INSTR可能有問題的東西,如「MyString的」和「MyStringTest」時只提供「MyString的」作爲變量。但是爲了避開它,你可以用一個特殊的字符和變量來填充原始值,這樣它會查找「; MyString;」代替。我之前也完成了這個技巧。 –

+0

哦優秀的小動作 - 將不得不記住它! –

+0

關閉......您還需要填寫列表中的第一個值。無論如何。做得好! –

1

你可以這樣做:

  1. 您的存儲過程的查詢轉換爲動態查詢和傳遞價值「」「ABC」「‘’等‘’」
  2. 實現分割函數將字符串分割成一個臨時表,並加入/查詢它。
  3. 你可以使用INSTR,但是它有一個技巧。

我寫了一個拆分函數,我工作的地方對於像這樣的東西來說效果很好。


INSTR招:你目前正在通過逗號作爲分隔符,所以這就是我的「絕招」使用,但你也可以使用一個分號。基本上,假設你想在'abc,def'中找到所有的東西。填充字符串使其看起來像',abc,def',然後填充搜索的值,使其看起來像',abc'。這樣,'abctest'和'testabc'找不到,而'abc'被找到。

SELECT 
    COUNT(*) 
INTO 
    counter 
FROM 
    test_pl_imp 
WHERE 
    INSTR(',' + rf + ',', ',' + column_name + ',') > 0; 

很抱歉,如果我不知道PL/SQL不夠好... +符號我認爲需要||,但我認爲你的想法。

1

您可以拆分輸入字符串,並使用臨時表或表格對象。這將允許優化器在您的列上使用索引。不要使用沒有綁定的動態SQL(出於安全性和性能的原因)。

下面是一個表格對象的例子。設置(10克,因爲它使用REGEXP_SUBSTR):

CREATE TYPE tab_varchar2 IS TABLE OF VARCHAR2(100);-- longest string 
/
CREATE OR REPLACE PROCEDURE test_pl(rf IN VARCHAR2) IS 
    lt tab_varchar2; 
    counter NUMBER; 
BEGIN 
    -- split parameter 
    SELECT rtrim(regexp_substr(str, '[^,]*,', 1, level), ',') 
    BULK COLLECT INTO lt 
    FROM (SELECT rf || ',' str FROM dual) 
    CONNECT BY level <= length(str) - length(replace(str, ',', '')); 
    -- your query 
    SELECT count(*) 
    INTO counter 
    FROM test_pl_imp 
    WHERE column_name IN (SELECT column_value FROM TABLE(lt)); 
    dbms_output.put_line(counter); 
END; 
/
相關問題