2009-11-11 56 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%的情况下,没关系)

相关问题