Oracle Nested Table predicate in where clause

。_饼干妹妹 提交于 2019-12-24 19:03:27

问题


I have a table that supposed to be searched with multiple columns, which can have multiple values

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   |                 |
-----------------------------------------------------------------

It looks fine to me as it does index lookup on more selective column. But I also have a requirement to search for all values if argument is not passed and I am really stuck with that.

The main question I think is how to write sql to search a table by multiple columns with multiple possible values in these columns? I want to be able to take advantage of bitmap indexes.

Should I maybe stick to Dynamic SQL for such task?

UPDATE. That is how I currently solved it for the moment.

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;

来源:https://stackoverflow.com/questions/19666943/oracle-nested-table-predicate-in-where-clause

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!