Предикат на Oracle Nested Table в клауза where

Имам таблица, в която се предполага, че се търси с множество колони, които могат да имат множество стойности

create table t as select * from all_objects;

create bitmap index IDX_DATA_OBJECT_ID on T (DATA_OBJECT_ID);
create bitmap index IDX_LAST_DDL_TIME on T (LAST_DDL_TIME);
create bitmap index IDX_OBJECT_NAME on T (OBJECT_NAME);
create bitmap index IDX_OBJECT_TYPE on T (OBJECT_TYPE);

create or replace type strarray as table of varchar2(4000)

CREATE OR REPLACE PROCEDURE p_search(op_cursor out SYS_REFCURSOR
                                ,a         strarray
                                ,b         strarray) IS
                                ca constant number:= a.count;
                                cb constant number:= b.count;
BEGIN
  OPEN op_cursor FOR
  SELECT /*+ gather_plan_statistics asda*/  *
    FROM t
   WHERE object_name IN (SELECT * FROM TABLE(a))
     AND object_type IN (SELECT * FROM TABLE(b));
END;

declare
  op_cursor sys_refcursor;
  c t%rowtype;
begin
  p_search(op_cursor,strarray('ICOL$'),strarray('TABLE'));
  loop
    fetch op_cursor into c;
    exit when op_cursor%notfound;
  end loop;
end;

-----------------------------------------------------------------
| Id  | Operation                             | Name            |
-----------------------------------------------------------------
|   0 | SELECT STATEMENT                      |                 |
|*  1 |  HASH JOIN SEMI                       |                 |
|   2 |   NESTED LOOPS                        |                 |
|   3 |    NESTED LOOPS                       |                 |
|   4 |     SORT UNIQUE                       |                 |
|   5 |      COLLECTION ITERATOR PICKLER FETCH|                 |
|   6 |     BITMAP CONVERSION TO ROWIDS       |                 |
|*  7 |      BITMAP INDEX SINGLE VALUE        | IDX_OBJECT_NAME |
|   8 |    TABLE ACCESS BY INDEX ROWID        | T               |
|   9 |   COLLECTION ITERATOR PICKLER FETCH   |                 |
-----------------------------------------------------------------

Изглежда добре за мен, тъй като прави търсене на индекс в по-селективна колона. Но също така имам изискване да търся всички стойности, ако аргументът не е предаден и наистина съм заседнал с това.

Основният въпрос, който мисля, е как да напиша sql за търсене в таблица по множество колони с множество възможни стойности в тези колони? Искам да мога да се възползвам от растерни индекси.

Трябва ли да се придържам към Dynamic SQL за такава задача?

АКТУАЛИЗИРАНЕ. Ето как го реших в момента.

create context my_ctx using p_search;

CREATE OR REPLACE FUNCTION in_list(p_string IN VARCHAR2) RETURN strarray AS
   l_string LONG DEFAULT p_string || ',';
   l_data   strarray := strarray();
   n        NUMBER;
BEGIN
   LOOP
      EXIT WHEN l_string IS NULL;
      n := instr(l_string, ',');
      l_data.extend;
      l_data(l_data.count) := ltrim(rtrim(substr(l_string, 1, n - 1)));
      l_string := substr(l_string, n + 1);
   END LOOP;

   RETURN l_data;
END;

CREATE OR REPLACE PROCEDURE p_search(op_cursor OUT SYS_REFCURSOR
                                    ,a         VARCHAR2
                                    ,b         VARCHAR2) IS
   l VARCHAR2(4000);
BEGIN
   l := 'SELECT /*+ gather_plan_statistics lvv3*/
       *
        FROM t
       WHERE 1=1';

   IF a IS NOT NULL
   THEN
      dbms_session.set_context('MY_CTX', 'OBJ_NAME', a);
      l := l || ' and t.object_name in (select /*+ cardinality (objn 5)*/ * from table(cast(in_list(sys_context( ''MY_CTX'',''OBJ_NAME'' )) as strarray)
                                             ) objn
                         )';
   END IF;

   IF b IS NOT NULL
   THEN
      dbms_session.set_context('MY_CTX', 'OBJ_TYPE', b);
      l := l || ' and t.object_type in (select /*+ cardinality (objt 5)*/ * from table(cast(in_list(sys_context( ''MY_CTX'',''OBJ_TYPE'' )) as strarray)
                                             ) objt
                         )';
   END IF;

   OPEN op_cursor FOR l;
   dbms_session.clear_context('MY_CTX');
END;

person Slava Lenskyy    schedule 29.10.2013    source източник
comment
За да изясним, проблемът ви е, че параметърът strarray, например a, може да е празен? И в този сценарий бихте искали object_name да не се взема под внимание в клаузата WHERE (т.е. всички възможни стойности на object_name трябва да бъдат взети под внимание)?   -  person Przemyslaw Kruglej    schedule 30.10.2013
comment
Може би просто трябва да промените предикатите, като например добавяне на or (select count(*) from table(a)) = 0.   -  person Jon Heller    schedule 30.10.2013
comment
@Przemyslaw Kruglej, да, прав си.   -  person Slava Lenskyy    schedule 30.10.2013
comment
Значи текущото ви решение работи, както очаквате? Не виждам никаква възможност да го направя по-кратък/по-лесен, освен (ако ще имате повече от 2 параметъра на масив) създаване на вложена функция за връщане на условие за низ, така че да не се налага да пишете отделно за всеки масив paremeter, но освен това не мога да се сетя за подобрение. Може би някой друг ще измисли нещо.   -  person Przemyslaw Kruglej    schedule 30.10.2013