2009-11-11 87 views
3

我想將多個值分配給一個變量並在where子句中使用該變量。如何將多個值分配給oracle中的字符串

對於防爆:

declare 

    v_filename varchar2(300) := ''('filename1','filename2')''; 
    cnt number; 

begin 

    select count(*) into cnt from table_name 
    where filename in v_filename; 

end; 

請指教。

感謝, 迪帕克

回答

1

你必須把整個查詢轉換爲字符串,然後執行該字符串EXECUTE IMMEDIATEsee the docs)。

1

除了「EXECUTE IMMEDIATE」之外,您還可以使用like,例如

declare 

    v_filename varchar2(300) := '(''filename1'',''filename2'')'; 
    cnt number; 

begin 

    select count(*) into cnt from table_name 
    where v_filename like '%'''||filename||'''%'; 

end; 

請注意,v_filename中的parenteses和逗號僅用於人類可讀性。這絕不是一個完美的解決方案,因爲它假定表中的文件名不包含某些特殊字符;如果在文件列上有一個索引(不以這種方式使用),它在性能方面也不好。

2

我會推薦閱讀Dynamic IN-Lists

EXECUTE IMMEDIATE也是一種可能性,但我不會推薦它,如果你不檢查IN字符串。

在快速剛剛撰寫了(使用 「動態IN-列表」 提出的第一種方法):

CREATE OR REPLACE TYPE t_varchar_tab AS TABLE OF VARCHAR2 (4000); 
CREATE OR REPLACE FUNCTION in_list (p_in_list IN VARCHAR2) RETURN t_varchar_tab 
AS 
    l_tab t_varchar_tab := t_varchar_tab(); 
    l_text VARCHAR2(32767) := p_in_list || ','; 
    l_idx NUMBER; 
BEGIN 
    LOOP 
    l_idx := INSTR(l_text, ','); 
    EXIT WHEN NVL(l_idx, 0) = 0; 
    l_tab.extend; 
    l_tab(l_tab.last) := TRIM(SUBSTR(l_text, 1, l_idx - 1)); 
    l_text := SUBSTR(l_text, l_idx + 1); 
    END LOOP; 

    RETURN l_tab; 
END; 

SELECT * FROM TABLE(in_list('filename1,filename2')); 
SELECT COUNT(*) INTO cnt FROM table_name WHERE filename IN (SELECT * FROM TABLE(in_list(v_filename))); 
3

你已經基本上2個選項。 1.使用動態查詢 2.使用集合

  1. 使用動態查詢動態地構造查詢在運行時,比運行它:

DECLARE 
    v_filename VARCHAR2(300) := '(''ALL_VIEWS'', ''ALL_TABLES'')'; 
--double quotes inside a string 
    cnt NUMBER; 

BEGIN 
execute immediate 'SELECT COUNT(*) INTO :cnt FROM all_views 
    WHERE view_name IN ' || v_filename 
    into cnt; 
    dbms_output.put_line('counted: ' || cnt); 
END; 
/

優點:容易寫,尤其是對於短查詢,快速 Disadvanteges:在您錯誤地在查詢字符串中粘貼用戶輸入的情況下可能的SQL注入,每次更改文件名列表時都會進行硬解析

  1. 使用集合。您創建一個集合類型,然後填充它並將其用作僞表。

create type tt_strings as table of varchar2(30); 

declare 
    cnt NUMBER; 
    v_condition tt_strings; 

begin 
    v_condition := tt_strings(); 
    v_condition.extend; 
    v_condition(1) := 'ALL_VIEWS'; 
    v_condition.extend; 
    v_condition(2) := 'ALL_TABLES'; 

    SELECT COUNT(*) 
    INTO cnt 
    FROM all_views o, TABLE(v_condition) x 
    WHERE x.column_value = o.VIEW_NAME; 
    dbms_output.put_line('counted: ' || cnt); 
end; 
/

優點:安全,維護與不止2個元素 Disadvatages大集合:你需要創建一個類型,更難代碼(首先),有點慢(在99%的情況下,沒關係)

相關問題