我有一个应该用多列搜索的表,它可以有多个值
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 来通过多列搜索表,这些列中有多个可能的值?我希望能够利用位图索引。
我应该坚持使用动态 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;