3

I want to assign mulitple values into a variable and use that variable in where-clause.

For Ex:

declare

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

begin

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

end;

Please advise.

Thanks, Deepak

4 Answers 4

3

you have basically 2 options. 1. Use dynamic query 2. Use collections

  1. With dynamic query you dynamically construct the query at runtime and than run it:

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;
/

Advantages: easy to write, especially for short queries, fast Disadvanteges: possible SQL INJECTION in cases when you wrongly paste user input in the query string, hard parse everytime you change the filename list

  1. Use collections. You create a collection type, then fill it and use it as a pseudo table.

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;
/

Advantages: Safe, maintainable for larger collections with more than just 2 elements Disadvatages: You need to create a type, Harder to code (at first), a bit slower (which in 99% cases doesn't matter)

Sign up to request clarification or add additional context in comments.

Comments

2

I would recommend reading Dynamic IN-Lists

EXECUTE IMMEDIATE is also a possibility, but I wouldn't recommend it if you don't check the IN string.

Just wrote on the quick(used the first method presented in "Dynamic IN-Lists"):

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)));

Comments

1

You must put the whole query into a string and then execute that string with EXECUTE IMMEDIATE (see the docs).

Comments

1

Alternatively to the "EXECUTE IMMEDIATE", you could use like, e.g.

declare

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

begin

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

end;

Note that the parenteses and the comma in v_filename are just for human readability. This is by no means a perfect solution, as it presumes that the filenames in your table do not contain some special characters; it's also bad in terms of performance if there is an index on the filename column (which is not used this way).

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.