8

In PL/SQL, how do I declare variable MyListOfValues that contains multiple values (MyValue1, MyValue2, etc.)

SELECT * 
FROM DatabaseTable 
WHERE DatabaseTable.Field in MyListOfValues

I am using Oracle SQL Developer

a_horse_with_no_name
  • 497,550
  • 91
  • 775
  • 843
Bob Smith
  • 83
  • 1
  • 1
  • 4
  • As far as I'm aware you can't do that (at least not in Oracle 11). I suggest that you build a dynamic query and execute that. Best of luck. – Bob Jarvis - Слава Україні Feb 05 '16 at 19:22
  • 1
    Possible duplicate of [How to load a large number of strings to match with oracle database?](http://stackoverflow.com/questions/34699223/how-to-load-a-large-number-of-strings-to-match-with-oracle-database) – MT0 Feb 05 '16 at 19:25

3 Answers3

8

Create the SQL type like this:

CREATE TYPE MyListOfValuesType AS TABLE OF VARCHAR2(4000);

And then use it in a SQL statement

DECLARE
  MyListOfValues MyListOfValuesType;
BEGIN
  MyListOfValues := MyListOfValuesType('MyValue1', 'MyValue2');

  FOR rec IN (
    SELECT *
    FROM DatabaseTable
    WHERE DatabaseTable.Field in (
      SELECT * FROM TABLE(MyListOfValues)
    )
  )
  LOOP
    ...
  END LOOP;
END;

Up until Oracle 11g, this only works with a SQL TABLE type, not with a PL/SQL TABLE type. With Oracle 12c, you could also use PL/SQL types.

Lukas Eder
  • 196,412
  • 123
  • 648
  • 1,411
6

Use a collection:

CREATE TYPE Varchar2TableType AS TABLE OF VARCHAR2(200);

Or use a built-in type like SYS.ODCIVARCHAR2LIST or SYS.ODCINUMBERLIST:

VARIABLE cursor REFCURSOR;

DECLARE
  your_collection SYS.ODCIVARCHAR2LIST := SYS.ODCIVARCHAR2LIST();
BEGIN
  your_collection.EXTEND( 100 );

  your_collection(  1) := 'Some value';
  your_collection(  2) := 'Some other value';
  -- ...
  your_collection(100) := DBMS_RANDOM.STRING( 'x', 20 );

  OPEN :cursor FOR
  SELECT t.*
  FROM   your_table t
         INNER JOIN
         TABLE( your_collection ) c
         ON t.id = c.COLUMN_VALUE;
END;
/

PRINT cursor;
MT0
  • 113,669
  • 10
  • 50
  • 103
2

How about using a WITH clause which basically builds a temp table? Not real reusable. You could use an array or I would argue joining to a lookup table would be better.

WITH MyListOfValues(col1) AS (
  select 'MyValue1' from dual union
  select 'MyValue2' from dual union
  select 'MyValue3' from dual 
)
SELECT * 
FROM DatabaseTable  
WHERE Column in (
  select col1
  from  MyListOfValues);
Gary_W
  • 9,149
  • 1
  • 18
  • 35