尘封飞扬 2009-09-14
在sql中经常会带有IN的子查询,如whereidin(1,2,3)。如果这样的语句在数据库中出现,将引起数据库的大量硬解析与共享池SQL碎片,
下面介绍种将这些Inlist给绑定起来:
1;首先针对数据类型和字符类型的绑定创建两个类型。
createorreplacetypenumtabletypeastableofnumber;
createorreplacetypevartabletypeastableofvarchar2(1000);
创建两个函数,分别来解析Inlist中的串
2:
CREATEORREPLACEFUNCTIONstr2numList(p_stringINvarchar2)RETURNnumtabletype
AS
v_strLONGDEFAULTp_string||',';
v_nNUMBER;
v_datanumtabletype:=numtabletype();
BEGIN
LOOP
v_n:=to_number(instr(v_str,','));
EXITWHEN(nvl(v_n,0)=0);
v_data.extend;
v_data(v_data.count):=ltrim(rtrim(substr(v_str,1,v_n-1)));
v_str:=substr(v_str,v_n+1);
ENDLOOP;
RETURNv_data;
END;
CREATEORREPLACEFUNCTIONstr2varList(p_stringINvarchar2)RETURNvartabletype
AS
v_strLONGDEFAULTp_string||',';
v_nvarchar2(2000);
v_datavartabletype:=vartabletype();
BEGIN
LOOP
v_n:=to_number(instr(v_str,','));
EXITWHEN(nvl(v_n,0)=0);
v_data.extend;
v_data(v_data.count):=ltrim(rtrim(substr(v_str,1,v_n-1)));
v_str:=substr(v_str,v_n+1);
ENDLOOP;
RETURNv_data;
END;
3:使用方式
添加Hint为了稳定执行计划
SELECT/*+ordereduser_nl(a,b)*/b.*FROMTABLE(str2numList(:bind0))a,ACCOUNTbWHEREb.id=a.column_value;
SELECT/*+ordereduser_nl(a,b)*/b.*FROMTABLE(str2numList('1,2,3'))a,ACCOUNTbWHEREb.id=a.column_value;
SELECT/*+leading(a)*/*FROMACCOUNTWHEREIDIN(SELECT*FROMTABLE(str2numList(:bind1))a);
SELECT/*+leading(a)*/*FROMACCOUNTWHEREID
参考资料:构件oracle高可用环境