How do you specify IN clause in a dynamic query using a variable?

前端 未结 4 684
北恋
北恋 2020-12-06 08:32

In PL/SQL, you can specify the values for the IN operator using concatenation:

v_sql := \'select field1
from table1
where field2 in (\' || v_list || \')\';
<         


        
4条回答
  •  青春惊慌失措
    2020-12-06 09:12

    As per @Marcin's answer you can't do this, however, there's a fair bit to add to that, as your query should actually work, i.e. run.

    Simply put, you cannot use a bind variable for a table or column. Not only that, bind variables they are assumed to be a character, so if you want a number you have to use to_number(:b1) etc.

    This is where your query falls down. As you're passing in a string Oracle assumes that your entire list is a single string. Thus you are effectively running:

    select field1
      from table1
    where field2 = v_list
    

    There is no reason why you can't do this a different way though. I'm going to assume you're dynamically creating v_list, which means that all you need to do is create this list differently. A series of or conditions is, purportedly :-), no different to using an in.

    By purportedly, I mean never rely on something that's untested. Although Tom does say in the link that there may be performance constraints there's no guarantee that it wasn't quicker than using in to begin with. The best thing to do is to run the trace on your query and his and see what difference there is, if any.

    SQL> set serveroutput on
    SQL>
    SQL> declare
      2
      3    l_string varchar2(32767);
      4    l_count number;
      5
      6  begin
      7
      8      for xx in ( select rownum as rnum, a.*
      9                    from user_tables a
     10                   where rownum < 20 ) loop
     11
     12        if xx.rnum = 1 then
     13          l_string := 'table_name = ''' || xx.table_name || '''';
     14        else
     15          l_string := l_string || ' or table_name = ''' || xx.table_name || '
    ''';
     16        end if;
     17
     18      end loop;
     19
     20      execute immediate 'select count(*)
     21                           from user_tables
     22                          where ' || l_string
     23                           into l_count
     24                                ;
     25
     26      dbms_output.put_line('count is ' || l_count);
     27
     28  end;
     29  /
    count is 19
    
    PL/SQL procedure successfully completed.
    

提交回复
热议问题