Oracle - вопрос CLAUSE при использовании с несколькими значениями, что делает его динамичным - PullRequest
4 голосов
/ 16 декабря 2010

Я только что провел час в Google и здесь, пытаясь получить прямой ответ, как это сделать в Oracle. Что мне нужно, так это возможность использовать команду select in, которая создается автоматически, например

select col1 from table1 where id.table IN ('1','2','3');

где значения id передаются хранимой процедуре внутри массива. Ассоциативный массив был определен так:

 TYPE varchar_array_type IS TABLE OF VARCHAR2 (40)      INDEX BY BINARY_INTEGER;

Есть ли простой, конкретный способ сделать это? спасибо

1 Ответ

5 голосов
/ 16 декабря 2010

К сожалению, если тип вашей коллекции определен в PL / SQL (а не в SQL), вы не можете использовать его в SQL, потому что механизм SQL не знает, как с ним справиться.

Если вы определили еготип коллекции в SQL, то есть

CREATE TYPE varchar_tbl
    IS TABLE OF varchar2(40);

Тогда вы можете сделать что-то вроде

SELECT col1
  FROM table1 t1
 WHERE t1.id IN (SELECT column_value
                   FROM TABLE( <<variable of type varchar2_tbl>> ) )

в зависимости от версии Oracle - синтаксис для использования коллекций в SQL развивался с течением времени.- более старые версии Oracle имели более сложный синтаксис.

Вы можете преобразовать ассоциативный массив PL / SQL (ваш VARCHAR_ARRAY_TYPE) в коллекцию вложенных таблиц SQL в PL / SQL, но это требует итерации по ассоциативному массиву и заполнениявложенный стол, который немного болит.Предполагая, что коллекция вложенных таблиц VARCHAR_TBL уже создана

SQL> CREATE OR REPLACE TYPE varchar_tbl
         IS TABLE OF varchar2(40);

, вы можете преобразовать ассоциативный массив во вложенную таблицу и использовать вложенную таблицу в SQL-выражении, подобном этому (используя SCOTT.EMPтаблица)

declare
  type varchar_array_type
    is table of varchar2(40)
       index by binary_integer;
  l_associative_array varchar_array_type;
  l_index             binary_integer;
  l_nested_table      varchar_tbl := new varchar_tbl();
  l_cnt               pls_integer;
begin
  l_associative_array( 1 ) := 'FORD';
  l_associative_array( 10 ) := 'JONES';
  l_associative_array( 100 ) := 'NOT A NAME';
  l_associative_array( 75 ) := 'SCOTT';
  l_index := l_associative_array.FIRST;
  while( l_index IS NOT NULL )
  loop
    l_nested_table.EXTEND;
    l_nested_table( l_nested_table.LAST ) :=
             l_associative_array( l_index );
    l_index := l_associative_array.NEXT( l_index );
  end loop;
  SELECT COUNT(*)
    INTO l_cnt
    FROM emp
   WHERE ename IN (SELECT column_value
                     FROM TABLE( l_nested_table ) );
  dbms_output.put_line( 'There are ' || l_cnt || ' employees with a matching name' );
end;

Поскольку преобразование между типами коллекций представляет собой сложную задачу, однако, как правило, было бы лучше просто использовать коллекцию вложенных таблиц (и передать ее в хранимую процедуру), если нетконкретная причина, по которой требуется ассоциативный массив.

...