Oracle
 sql >> Datenbank >  >> RDS >> Oracle

Oracle - In CLAUSE-Frage bei Verwendung mit mehreren Werten, wodurch es dynamisch wird

Wenn Ihr Sammlungstyp in PL/SQL (und nicht in SQL) definiert ist, können Sie ihn leider nicht in SQL verwenden, da die SQL-Engine nicht weiß, wie er damit umgehen soll.

Wenn Sie stattdessen den Sammlungstyp in SQL definiert haben, also

CREATE TYPE varchar_tbl
    IS TABLE OF varchar2(40);

Dann können Sie so etwas tun wie

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

Abhängig von der Oracle-Version – die Syntax für die Verwendung von Sammlungen in SQL hat sich im Laufe der Zeit weiterentwickelt – hatten ältere Versionen von Oracle eine komplexere Syntax.

Sie können ein assoziatives PL/SQL-Array (Ihr VARCHAR_ARRAY_TYPE) in eine verschachtelte SQL-Tabellensammlung in PL/SQL konvertieren, aber dazu müssen Sie das assoziative Array durchlaufen und die verschachtelte Tabelle füllen, was ein bisschen mühsam ist. Angenommen, der VARCHAR_TBL verschachtelte Tabellensammlung wurde bereits erstellt

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

Sie können vom assoziativen Array in die verschachtelte Tabelle konvertieren und die verschachtelte Tabelle in einer SQL-Anweisung wie dieser verwenden (unter Verwendung der SCOTT.EMP-Tabelle)

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;

Da das Konvertieren zwischen Sammlungstypen jedoch etwas mühsam ist, sollten Sie im Allgemeinen besser nur die verschachtelte Tabellensammlung verwenden (und diese an die gespeicherte Prozedur übergeben), es sei denn, es gibt einen bestimmten Grund, warum das assoziative Array benötigt wird.