복붙노트

[SQL] 당신은 어떻게 변수를 사용하여 동적 쿼리에서 IN 절을 지정합니까?

SQL

당신은 어떻게 변수를 사용하여 동적 쿼리에서 IN 절을 지정합니까?

PL / SQL에서는 연결을 사용하여 IN 연산자에 대한 값을 지정할 수 있습니다 :

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

이 변수를 사용하여 동일한 작업을 수행 할 수 있습니까?

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

그렇다면, 어떻게?

편집 : 마르신의 대답을 참조하면, 어떻게 결과 테이블에서 선택합니까?

declare

cursor c_get_csv_as_tables is
select in_list(food_list) food_list
from emp_food
where emp_type = 'PERM';

cursor c_get_food_list (v_food_table varchar2Table)is
select *
from v_food_table;

begin
    for i in c_get_csv_as_tables loop
        for j in c_get_food_list(i.food_list) loop
            dbms_output.put_line(j.element);
        end loop;
    end loop;
end;

나는 다음과 같은 오류가 발생합니다 :

ORA-06550: line 10, column 6:
PL/SQL: ORA-00942: table or view does not exist
ORA-06550: line 9, column 1:
PL/SQL: SQL Statement ignored
ORA-06550: line 15, column 34:
PLS-00364: loop index variable 'J' use is invalid
ORA-06550: line 15, column 13:
PL/SQL: Statement ignored

해결법

  1. ==============================

    1.@Sathya 링크에서, 당신은 VARRAY를 결합 할 수처럼 (나는 @Codo 예를했다)

    @Sathya 링크에서, 당신은 VARRAY를 결합 할 수처럼 (나는 @Codo 예를했다)

    CREATE OR REPLACE TYPE str_tab_type IS VARRAY(10) OF VARCHAR2(200);
    /
    DECLARE
      l_str_tab str_tab_type;
      l_count NUMBER;
      v_sql varchar2(3000);
    BEGIN
      l_str_tab := str_tab_type();
      l_str_tab.extend(2);
      l_str_tab(1) := 'TABLE';
      l_str_tab(2) := 'INDEX';
    
      v_sql := 'SELECT COUNT(*) FROM all_objects WHERE object_type IN (SELECT COLUMN_VALUE FROM TABLE(:v_list))';
    
      execute immediate v_sql into l_count using l_str_tab;
    
      dbms_output.put_line(l_count);
    END;
    /
    

    UPDATE : 첫 번째 명령으로 대체 할 수있다 :

    CREATE OR REPLACE TYPE str_tab_type IS TABLE OF VARCHAR2(200);
        /
    

    다음 전화 :

    l_str_tab.extend(1);
    

    때 이제까지 당신이 값을 추가

  2. ==============================

    2.불행하게도 당신은 그러나 당신은 테이블 기능을 사용할 수 있습니다,이 같은 목록을 바인딩 할 수 없습니다. 이 읽기

    불행하게도 당신은 그러나 당신은 테이블 기능을 사용할 수 있습니다,이 같은 목록을 바인딩 할 수 없습니다. 이 읽기

    여기에 귀하의 코드를 기반으로 사용의 예입니다 :

    declare
    
    cursor c_get_csv_as_tables is
    select in_list(food_list) food_list
    from emp_food
    where emp_type = 'PERM';
    
    cursor c_get_food_list (v_food_table varchar2Table)is
    select column_value food
    from TABLE(v_food_table);
    
    begin
        for i in c_get_csv_as_tables loop
            for j in c_get_food_list(i.food_list) loop
                dbms_output.put_line(j.food);
            end loop;
        end loop;
    end;
    

    나는 여기에 COLUMN_VALUE 의사 열을 사용

  3. ==============================

    3.바인드 변수는 절 "의"오라클 SQL 쿼리에 사용할 수 있습니다.

    바인드 변수는 절 "의"오라클 SQL 쿼리에 사용할 수 있습니다.

    10g에서 작동; 나는 다른 버전에 대해 알고하지 않습니다.

    바인드 변수는 4000 자 VARCHAR의 최대이다.

    예 : 쉼표로 구분 된 값리스트를 포함 바인드 변수, 예를 들어

    : Bindvar = 1,2,3,4,5

    select * from mytable
      where myfield in
        (
          SELECT regexp_substr(:bindvar,'[^,]+', 1, level) items
          FROM dual
          CONNECT BY regexp_substr(:bindvar, '[^,]+', 1, level) is not null
        );
    
  4. ==============================

    4.이 작업을 수행 할 수 없습니다 마르신의 답변 @ 당으로, 그러나, 공정한 비트가에 추가 쿼리로해야 실제로 작업, 즉 실행이있다.

    이 작업을 수행 할 수 없습니다 마르신의 답변 @ 당으로, 그러나, 공정한 비트가에 추가 쿼리로해야 실제로 작업, 즉 실행이있다.

    간단하게 말해서, 당신은 테이블이나 열에 대한 바인드 변수를 사용할 수 없습니다. 뿐만 아니라 당신은 숫자를 원하는 경우, 바인드가 문자를로 간주되는 변수는, 그래서 당신이 사용 TO_NUMBER에 가지고 (: B1) 등

    쿼리가 아래로 떨어지는 곳이다. 당신이 문자열에 전달하는 것처럼 오라클은 전체 목록은 단일 문자열 있다고 가정합니다. 따라서 효과적으로 실행 :

    select field1
      from table1
    where field2 = v_list
    

    당신이 비록 다른 방법으로 할 수없는 이유가 없다. 나는 당신이 동적으로 당신이 할 필요가 다르게이 목록을 만들 수 있음을 의미 v_list을 작성한다고 가정하겠습니다. 또는 일련의 조건은에을 이용 다르지 :-) 의도적, 없다.

    소문에, 나는 검증되지 않은 무언가에 의존하지 의미한다. 톰 성능 제약이있을 수있는 링크라고 않지만 그것은 시작에 사용하는 것보다하지 빨랐다 않는다는 보장은 없습니다. 가장 좋은 것은 어떤 경우,이 쿼리와 그의 볼 무엇 차이에 대한 추적을 실행하는 것입니다.

    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.
    
  5. from https://stackoverflow.com/questions/8967652/how-do-you-specify-in-clause-in-a-dynamic-query-using-a-variable by cc-by-sa and MIT license