如何在oracle中为字符串分配多个值

时间:2009-11-11 12:35:55

标签: sql oracle

我想将多个值分配给变量,并在where子句中使用该变量。

对于Ex:

declare

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

begin

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

end;

请告知。

谢谢, 迪帕克

4 个答案:

答案 0 :(得分:3)

你基本上有2个选择。 1.使用动态查询 2.使用馆藏

  1. 使用动态查询,您可以在运行时动态构造查询,然后运行它:
  2. 
    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 INJECTION,每次更改文件名列表时都会进行硬解析

    1. 使用馆藏。您创建一个集合类型,然后填充它并将其用作伪表。
    2. 
      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%的情况下无关紧要)

答案 1 :(得分: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)));

答案 2 :(得分:1)

您必须将整个查询放入一个字符串中,然后使用EXECUTE IMMEDIATEsee the docs)执行该字符串。

答案 3 :(得分: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和逗号仅用于人类可读性。这绝不是一个完美的解决方案,因为它假设表中的文件名不包含一些特殊字符;如果文件名列上有索引(这不是以这种方式使用),那么在性能方面也是不好的。