- 浏览: 9440 次
- 性别:
- 来自: 武汉
-
最近访客 更多访客>>
最新评论
-
armorking:
用CLOB类型作返回值,刚才的问题得到解决
于是写了两个函数: ...
讨论一个比较复杂的查询语优化问题 -
armorking:
<div class="quote_title ...
讨论一个比较复杂的查询语优化问题 -
chenhj520:
to: armorking
那个自定义聚集函数, ...
讨论一个比较复杂的查询语优化问题 -
armorking:
<div class="quote_title ...
讨论一个比较复杂的查询语优化问题 -
chenhj520:
to:armorking
非常感谢你的建议.
请问你是 ...
讨论一个比较复杂的查询语优化问题
一条查询语句中包括有多个函数,函数的作用主要是主组合字符串.两个数据查询出来花了快一分多钟.
查询的两条数据结果:
1 990000000000001741 2008-04-14 18:16 铁塔 包1 阿塔其大一互电器有限公司、安徽宏鼎互感器有限公司、安徽宏源电力铁塔制造股份合作公司、安徽宏源线路器材有限公司、安徽明都电力线缆有限公司、鞍山铁塔制造总厂、鞍山万事达电力有限公司、宝丰电缆有限公司、宝鸡铁塔厂、宝胜普睿司曼电缆有限公司、保定保菱变压器有限公司、保定电力修造厂、保定市华北电力线材制造有限公司、保定天威保变电气股份有限公司、保定天威互感器有限公司、北京ABB高压开关设备有限公司、北京北开电气股份有限公司、北京电力设备总厂、北京电研华源电力技术有限公司、北京宏达日新电机有限公司、北京华美煜力电力技术有限公司、北京潞电电气设备有限公司、北京送变电公司线路器材厂、长春聚德龙铁塔集团有限公司、长春三鼎变压器有限公司、常州东芝变压器有限公司、常州华银电线电缆有限公司、常州市武进恒通金属钢丝有限公司、成都双星变压器有限公司、重庆ABB变压器有限公司、重庆市江津电力线路构件厂、重庆顺泰铁塔制造有限公司、重庆渝能泰山电线电缆有限公司、传奇电气(沈阳)有限公司、大连电瓷有限公司、大连互感器有限公司、东莞市高能实业有限公司、恩基客(上海)商贸有限公司、菲尔普斯.道奇(烟台)电缆有限公司、福建德和铁塔设备制造有限公司、福建电建杆塔制造有限责任公司、福建南平太阳电缆股份有限公司、抚顺电瓷制造有限公司、甘肃长通电缆科技股份有限公司、甘肃诚信电线电缆有限责任公司、赣州联盛电力器材有限公司、广东新亚光电缆实业有限公司、广州华盛避雷器实业有限公司、广州市迈克林电力有限公司、广州维奥伊林变压器有限公司 超级管理员 未导出 T120007 990000000000003243 1 超级管理员 990000000000000001 0 a 1 产品型式不满足要求
2 990000000000001761 2008-04-15 11:54 铁塔 包2、包4、包5、包6、包7、包8、包9、包10、包11、包12、包13、包14、包15、包16、包17、包18、包20、包22、包23、包24、包25、包26、包27、包28、包29、包30、包31、包33、包34、包35、包36、包37、包38、包39、包40、包41、包42、包43、包44、包45、包46、包48、包49、包50、包51、包52、包53、包54、包55、包56、包57、包58、包59、包60、包61、包62、包63、包64、包65、包66、包67、包68、包69 重庆顺泰铁塔制造有限公司 EP46 未导出 T120008 990000000000003243 1 EP46 990000000000006222 0 a 1 投标人资格条件不满足要求(缺少鉴定证书或许可证)
两条数据花了61.016秒.
问题主要在几个组合字符串的函数上.
取审批单包名的函数.
一个审批单对应的包数据比较多是,查询出来数据非常慢.
获得审批单对应供应商函数
得到审批单废标原因函数
正常情况下直接查询这几个函数非常快.
第一条查询只花费时间0.016秒,第二条数据,花费0.015秒
当我去掉这几个函数时同形个查询语只用了0.19秒.
能提供的点优化思路吗?谢谢各位了
我在执行语句测试时,一个审批单对应有63个包.使用分组和自定义的聚函数的产生的
ORA-06052:PL/SQL :数据字或值错误:字符串缓冲区太小.
ORA-O6512:在BID.STR_CONN_TYPE,line 47
在47行代码是
tmp_vStr VARCHAR2(4000)定义为最大值.
其聚集函数为你提供的函数.
我测试了一下,当字符串长度超出4000的时候,是会发生错误
在oracle函数中,允许定义的字符串最大长度是32767
所以把函数中定义的VcArrayType改成VARCHAR2(32767)
并且把tmp_vStr 类型声明为VARCHAR2(32767)的时候
这个字符串拼接处理就不会出错了
但是,当把这个字符串作为varchar或者是varchar2类型的返回值来使用的时候,最大长度仍然不能超过4000
所以,为了避免出错,在返回值之前必须作substr处理
如下:
当然,这样一来,在实际数据长度超过4000的时候,就得不到业务需求的结果了
我也测试了原先的fun_get_Repeal_CompanyName的做法
基于同样的原因,这种做法在在实际数据长度超过4000的时候也是会报错的
我想,在使用varchar型的返回值的函数实现这个业务的时候,这种现象是不可避免的
所以,oracle的解决办法可能就是使用clob类型的返回值来实现这个函数
这一点目前还尚待证实
不过,使用clob返回值的话,java端取数据的时候就要麻烦不少了
那个自定义聚集函数,是用pl/sql写的,
可以在group by 语句中直接把它当作SUM,MIN之类的函数一样使用
我曾经测试过,应该是好使的
至于pl/sql代码的格式设置
我是做了一个sql整形用的java函数
不过这个sql整形程序还不是很完善,有时候还需要在生成结果的基础上作些调整
select distinct br.repeal_id, to_char(br.create_date, 'yyyy-MM-dd hh24:mi') as create_date, pbo.object_alias_name objectName, fun_get_Repeal_package(br.repeal_id) packageName, br.is_audit, fun_get_Repeal_CompanyName(br.repeal_id) companyName, (select user_name from sm_t_user where user_id = br.create_user_id) user_name, case br.is_group_report when 2 then '已修改' when 1 then '已导出' when 0 then '未导出' end as is_type, br.object_number, bpd.project_id, br.repeal_status, (select stu.user_name from be_t_flow_log btf, sm_t_user stu where btf.sub_user_id = stu.user_id and br.repeal_status = btf.billstatus and br.repeal_id = btf.repeal_id and btf.flow_able <> -1 and rownum = 1) ruser_name, br.create_user_id, br.is_group_report, case when ((select count(*) from be_t_flow_log btw where btw.flow_able = 0 and btw.repeal_id = br.repeal_id and btw.billstatus = 3 and btw.audit_status is null and ((select count(*) from be_t_flow_log btlg where btlg.flow_able = -1 and btlg.repeal_id = br.repeal_id) > 0)) > 0) then 'red' else '' end as color, 'a' indexNo, br.blank_out, fun_get_Repeal_Reason(br.repeal_id) repeal_reason from be_t_repeal br, be_t_repeal_package brp, be_t_project_detail bpd, pa_t_bid_package pbp, pa_t_bid_object pbo, be_t_providers bp, be_t_repeal_package btr, BE_T_FLOW_LOG BTFL where br.repeal_id = brp.repeal_id and brp.project_device_id = bpd.project_device_id and bpd.bid_package_id = pbp.bid_package_id and pbp.bid_object_id = pbo.bid_object_id and brp.provider_id = bp.provider_id and br.repeal_id = btr.repeal_id and br.repeal_id = btfl.repeal_id and btfl.flow_type = 1 and br.project_id = 990000000000003243;
查询的两条数据结果:
1 990000000000001741 2008-04-14 18:16 铁塔 包1 阿塔其大一互电器有限公司、安徽宏鼎互感器有限公司、安徽宏源电力铁塔制造股份合作公司、安徽宏源线路器材有限公司、安徽明都电力线缆有限公司、鞍山铁塔制造总厂、鞍山万事达电力有限公司、宝丰电缆有限公司、宝鸡铁塔厂、宝胜普睿司曼电缆有限公司、保定保菱变压器有限公司、保定电力修造厂、保定市华北电力线材制造有限公司、保定天威保变电气股份有限公司、保定天威互感器有限公司、北京ABB高压开关设备有限公司、北京北开电气股份有限公司、北京电力设备总厂、北京电研华源电力技术有限公司、北京宏达日新电机有限公司、北京华美煜力电力技术有限公司、北京潞电电气设备有限公司、北京送变电公司线路器材厂、长春聚德龙铁塔集团有限公司、长春三鼎变压器有限公司、常州东芝变压器有限公司、常州华银电线电缆有限公司、常州市武进恒通金属钢丝有限公司、成都双星变压器有限公司、重庆ABB变压器有限公司、重庆市江津电力线路构件厂、重庆顺泰铁塔制造有限公司、重庆渝能泰山电线电缆有限公司、传奇电气(沈阳)有限公司、大连电瓷有限公司、大连互感器有限公司、东莞市高能实业有限公司、恩基客(上海)商贸有限公司、菲尔普斯.道奇(烟台)电缆有限公司、福建德和铁塔设备制造有限公司、福建电建杆塔制造有限责任公司、福建南平太阳电缆股份有限公司、抚顺电瓷制造有限公司、甘肃长通电缆科技股份有限公司、甘肃诚信电线电缆有限责任公司、赣州联盛电力器材有限公司、广东新亚光电缆实业有限公司、广州华盛避雷器实业有限公司、广州市迈克林电力有限公司、广州维奥伊林变压器有限公司 超级管理员 未导出 T120007 990000000000003243 1 超级管理员 990000000000000001 0 a 1 产品型式不满足要求
2 990000000000001761 2008-04-15 11:54 铁塔 包2、包4、包5、包6、包7、包8、包9、包10、包11、包12、包13、包14、包15、包16、包17、包18、包20、包22、包23、包24、包25、包26、包27、包28、包29、包30、包31、包33、包34、包35、包36、包37、包38、包39、包40、包41、包42、包43、包44、包45、包46、包48、包49、包50、包51、包52、包53、包54、包55、包56、包57、包58、包59、包60、包61、包62、包63、包64、包65、包66、包67、包68、包69 重庆顺泰铁塔制造有限公司 EP46 未导出 T120008 990000000000003243 1 EP46 990000000000006222 0 a 1 投标人资格条件不满足要求(缺少鉴定证书或许可证)
两条数据花了61.016秒.
问题主要在几个组合字符串的函数上.
取审批单包名的函数.
create or replace function fun_get_Repeal_package(p_repeal_id varchar) return varchar as cursor cur is select distinct pbp.package_name, pbp.package_order, pbp.child_order from be_t_repeal br, be_t_repeal_package brp, be_t_project_detail bpd, pa_t_bid_package pbp pa_t_bid_object pbo, where br.repeal_id = brp.repeal_id and brp.project_device_id = bpd.project_device_id and bpd.bid_package_id = pbp.bid_package_id and pbp.bid_object_id = pbo.bid_object_id and brp.provider_id = bp.provider_id and br.repeal_id = p_repeal_id order by pbp.package_order || pbp.child_order, pbp.child_order, pbp.package_name; v_package varchar2(1000); begin v_package := ''; for cur_repeal in cur loop v_package := v_package || cur_repeal.package_name || '、'; end loop; v_package := substr(v_package, 1, length(v_package) - 1); return v_package; end;
一个审批单对应的包数据比较多是,查询出来数据非常慢.
获得审批单对应供应商函数
create or replace function fun_get_Repeal_CompanyName(p_repeal_id varchar) return varchar as cursor cur is select distinct bp.company_fullname from be_t_repeal br, be_t_repeal_package brp, be_t_project_detail bpd, be_t_providers bp where br.repeal_id = brp.repeal_id and brp.project_device_id = bpd.project_device_id and brp.provider_id = bp.provider_id and br.repeal_id = p_repeal_id order by nlssort(bp.company_fullname, 'NLS_SORT=SCHINESE_PINYIN_M'); v_company_name varchar2(1000); begin v_company_name := ''; for cur_repeal in cur loop v_company_name := v_company_name || cur_repeal.company_fullname || '、'; end loop; v_company_name := substr(v_company_name, 1, length(v_company_name) - 1); return v_company_name; end;
得到审批单废标原因函数
create or replace function fun_get_Repeal_Reason(p_repeal_id varchar) return varchar as v_reason_conten varchar(1000); cursor cur is select distinct bt.reason_content from be_t_repeal_reson bt, be_t_repeal_package btrp where bt.repeal_reason_id = btrp.repeal_reason_id and btrp.repeal_id = p_repeal_id; begin v_reason_conten:=''; for cur_re in cur loop v_reason_conten:=v_reason_conten||cur_re.reason_content||'、'; end loop; v_reason_conten := substr(v_reason_conten, 1, length(v_reason_conten) - 1); return v_reason_conten; end;
正常情况下直接查询这几个函数非常快.
select fun_get_repeal_companyname(990000000000001761) from dual; select fun_get_repeal_package(990000000000001761) from dual;
第一条查询只花费时间0.016秒,第二条数据,花费0.015秒
当我去掉这几个函数时同形个查询语只用了0.19秒.
能提供的点优化思路吗?谢谢各位了
评论
8 楼
armorking
2008-04-17
用CLOB类型作返回值,刚才的问题得到解决
于是写了两个函数:CONNSTR_TO_VARCHAR和CONNSTR_TO_CLOB
分别处理VARCHAR与CLOB返回值
于是写了两个函数:CONNSTR_TO_VARCHAR和CONNSTR_TO_CLOB
分别处理VARCHAR与CLOB返回值
--自定義集約関数→SORTED DROP FUNCTION CONNSTR_TO_VARCHAR / DROP TYPE BODY VARCHAR_STR_CONN_TYPE / DROP TYPE VARCHAR_STR_CONN_TYPE / DROP FUNCTION CONNSTR_TO_CLOB / DROP TYPE BODY CLOB_STR_CONN_TYPE / DROP TYPE CLOB_STR_CONN_TYPE / DROP TYPE VcArrayType / CREATE OR REPLACE TYPE VcArrayType IS TABLE OF VARCHAR2(4000); / ------------------------------------------- --1.CONNSTR_TO_VARCHAR CREATE OR REPLACE TYPE VARCHAR_STR_CONN_TYPE AS OBJECT ( --vStr VARCHAR2(4000), vStr VcArrayType, STATIC FUNCTION ODCIAggregateInitialize(sctx IN OUT VARCHAR_STR_CONN_TYPE ) RETURN NUMBER, MEMBER FUNCTION ODCIAggregateIterate(SELF IN OUT VARCHAR_STR_CONN_TYPE , VALUE IN VARCHAR2 ) RETURN NUMBER, MEMBER FUNCTION ODCIAggregateMerge(SELF IN OUT VARCHAR_STR_CONN_TYPE, ctx2 IN VARCHAR_STR_CONN_TYPE) RETURN NUMBER, MEMBER FUNCTION ODCIAggregateTerminate(SELF IN VARCHAR_STR_CONN_TYPE, returnValue OUT VARCHAR2, flags IN NUMBER) RETURN NUMBER ); / CREATE OR REPLACE TYPE BODY VARCHAR_STR_CONN_TYPE IS STATIC FUNCTION ODCIAggregateInitialize(sctx IN OUT VARCHAR_STR_CONN_TYPE) RETURN NUMBER IS BEGIN sctx := VARCHAR_STR_CONN_TYPE(VcArrayType()); RETURN ODCIConst.Success; END; MEMBER FUNCTION ODCIAggregateIterate(SELF IN OUT VARCHAR_STR_CONN_TYPE, VALUE IN VARCHAR2 ) RETURN NUMBER IS BEGIN vStr.EXTEND; vStr(vStr.COUNT) := VALUE; RETURN ODCIConst.Success; END; MEMBER FUNCTION ODCIAggregateMerge(SELF IN OUT VARCHAR_STR_CONN_TYPE, ctx2 IN VARCHAR_STR_CONN_TYPE) RETURN NUMBER IS BEGIN RETURN ODCIConst.Success; END; MEMBER FUNCTION ODCIAggregateTerminate(SELF IN VARCHAR_STR_CONN_TYPE, returnValue OUT VARCHAR2, flags IN NUMBER) RETURN NUMBER IS tmp_vStr VARCHAR2(4000); loop_vstr VARCHAR2(4000); sperator VARCHAR2(255); sperator_size NUMBER; current_size NUMBER; BEGIN sperator := '、'; sperator_size := LENGTHB(sperator); current_size := 0; FOR rec_Value IN ( SELECT column_value FROM TABLE(vStr) ORDER BY column_value ) LOOP loop_vstr := rec_Value.column_value; current_size := current_size + sperator_size + LENGTHB(loop_vstr); IF (current_size <= 4000) THEN tmp_vStr := tmp_vStr || sperator || loop_vstr; END IF; END LOOP; returnValue := LTRIM(tmp_vStr, sperator); RETURN ODCIConst.Success; END; END; / CREATE OR REPLACE FUNCTION CONNSTR_TO_VARCHAR(input VARCHAR2) RETURN VARCHAR2 PARALLEL_ENABLE AGGREGATE USING VARCHAR_STR_CONN_TYPE; / ------------------------------------------- --2.CONNSTR_TO_CLOB CREATE OR REPLACE TYPE CLOB_STR_CONN_TYPE AS OBJECT ( --vStr VARCHAR2(4000), vStr VcArrayType, STATIC FUNCTION ODCIAggregateInitialize(sctx IN OUT CLOB_STR_CONN_TYPE ) RETURN NUMBER, MEMBER FUNCTION ODCIAggregateIterate(SELF IN OUT CLOB_STR_CONN_TYPE , VALUE IN VARCHAR2 ) RETURN NUMBER, MEMBER FUNCTION ODCIAggregateMerge(SELF IN OUT CLOB_STR_CONN_TYPE, ctx2 IN CLOB_STR_CONN_TYPE) RETURN NUMBER, MEMBER FUNCTION ODCIAggregateTerminate(SELF IN CLOB_STR_CONN_TYPE, returnValue OUT CLOB, flags IN NUMBER) RETURN NUMBER ); / CREATE OR REPLACE TYPE BODY CLOB_STR_CONN_TYPE IS STATIC FUNCTION ODCIAggregateInitialize(sctx IN OUT CLOB_STR_CONN_TYPE) RETURN NUMBER IS BEGIN sctx := CLOB_STR_CONN_TYPE(VcArrayType()); RETURN ODCIConst.Success; END; MEMBER FUNCTION ODCIAggregateIterate(SELF IN OUT CLOB_STR_CONN_TYPE, VALUE IN VARCHAR2 ) RETURN NUMBER IS BEGIN vStr.EXTEND; vStr(vStr.COUNT) := VALUE; RETURN ODCIConst.Success; END; MEMBER FUNCTION ODCIAggregateMerge(SELF IN OUT CLOB_STR_CONN_TYPE, ctx2 IN CLOB_STR_CONN_TYPE) RETURN NUMBER IS BEGIN RETURN ODCIConst.Success; END; MEMBER FUNCTION ODCIAggregateTerminate(SELF IN CLOB_STR_CONN_TYPE, returnValue OUT CLOB, flags IN NUMBER) RETURN NUMBER IS tmp_vStr VARCHAR2(32767); loop_vstr VARCHAR2(4000); sperator VARCHAR2(255); sperator_size NUMBER; is_null_flg NUMBER; current_size NUMBER; BEGIN sperator := '、'; sperator_size := LENGTHB(sperator); is_null_flg := 0; current_size := 0; FOR rec_Value IN ( SELECT column_value FROM TABLE(vStr) ORDER BY column_value ) LOOP loop_vstr := rec_Value.column_value; current_size := current_size + sperator_size + LENGTHB(loop_vstr); IF (current_size > 32767) THEN IF (is_null_flg = 1) THEN DBMS_LOB.APPEND(returnValue, TO_CLOB(tmp_vStr)); END IF; IF (is_null_flg = 0) THEN tmp_vStr := LTRIM(tmp_vStr, sperator); returnValue := TO_CLOB(tmp_vStr); is_null_flg := 1; END IF; tmp_vStr := ''; current_size := 0; END IF; tmp_vStr := tmp_vStr || sperator || loop_vstr; END LOOP; IF (is_null_flg = 1) THEN DBMS_LOB.APPEND(returnValue, TO_CLOB(tmp_vStr)); END IF; IF (is_null_flg = 0) THEN tmp_vStr := LTRIM(tmp_vStr, sperator); returnValue := TO_CLOB(tmp_vStr); END IF; RETURN ODCIConst.Success; END; END; / CREATE OR REPLACE FUNCTION CONNSTR_TO_CLOB(input VARCHAR2) RETURN CLOB PARALLEL_ENABLE AGGREGATE USING CLOB_STR_CONN_TYPE; /
7 楼
armorking
2008-04-17
chenhj520 写道
我在执行语句测试时,一个审批单对应有63个包.使用分组和自定义的聚函数的产生的
ORA-06052:PL/SQL :数据字或值错误:字符串缓冲区太小.
ORA-O6512:在BID.STR_CONN_TYPE,line 47
在47行代码是
tmp_vStr := tmp_vStr || '、' || rec_Value.column_value;
tmp_vStr VARCHAR2(4000)定义为最大值.
其聚集函数为你提供的函数.
我测试了一下,当字符串长度超出4000的时候,是会发生错误
在oracle函数中,允许定义的字符串最大长度是32767
所以把函数中定义的VcArrayType改成VARCHAR2(32767)
并且把tmp_vStr 类型声明为VARCHAR2(32767)的时候
tmp_vStr := tmp_vStr || '、' || rec_Value.column_value;
这个字符串拼接处理就不会出错了
但是,当把这个字符串作为varchar或者是varchar2类型的返回值来使用的时候,最大长度仍然不能超过4000
所以,为了避免出错,在返回值之前必须作substr处理
如下:
--自定義集約関数→SORTED DROP FUNCTION ConnStr / DROP TYPE BODY STR_CONN_TYPE / DROP TYPE STR_CONN_TYPE / DROP TYPE VcArrayType / CREATE OR REPLACE TYPE VcArrayType IS TABLE OF VARCHAR2(32767); / CREATE OR REPLACE TYPE STR_CONN_TYPE AS OBJECT ( --vStr VARCHAR2(4000), vStr VcArrayType, STATIC FUNCTION ODCIAggregateInitialize(sctx IN OUT STR_CONN_TYPE ) RETURN NUMBER, MEMBER FUNCTION ODCIAggregateIterate(SELF IN OUT STR_CONN_TYPE , VALUE IN VARCHAR2 ) RETURN NUMBER, MEMBER FUNCTION ODCIAggregateMerge(SELF IN OUT STR_CONN_TYPE, ctx2 IN STR_CONN_TYPE) RETURN NUMBER, MEMBER FUNCTION ODCIAggregateTerminate(SELF IN STR_CONN_TYPE, returnValue OUT VARCHAR2, flags IN NUMBER) RETURN NUMBER ); / CREATE OR REPLACE TYPE BODY STR_CONN_TYPE IS STATIC FUNCTION ODCIAggregateInitialize(sctx IN OUT STR_CONN_TYPE) RETURN NUMBER IS BEGIN --sctx := STR_CONN_TYPE(NULL); sctx := STR_CONN_TYPE(VcArrayType()); RETURN ODCIConst.Success; END; MEMBER FUNCTION ODCIAggregateIterate(SELF IN OUT STR_CONN_TYPE, VALUE IN VARCHAR2 ) RETURN NUMBER IS BEGIN --SELF.vStr := SELF.vStr || ';' || VALUE; vStr.EXTEND; vStr(vStr.COUNT) := VALUE; RETURN ODCIConst.Success; END; MEMBER FUNCTION ODCIAggregateMerge(SELF IN OUT STR_CONN_TYPE, ctx2 IN STR_CONN_TYPE) RETURN NUMBER IS BEGIN RETURN ODCIConst.Success; END; MEMBER FUNCTION ODCIAggregateTerminate(SELF IN STR_CONN_TYPE, returnValue OUT VARCHAR2, flags IN NUMBER) RETURN NUMBER IS tmp_vStr VARCHAR2(32767); BEGIN --returnValue := LTRIM(SELF.vStr,';'); FOR rec_Value IN ( SELECT column_value FROM TABLE(vStr) --ORDER BY to_number(column_value) ORDER BY column_value ) LOOP --tmp_vStr := tmp_vStr || '_' || rec_Value.column_value; tmp_vStr := tmp_vStr || '、' || rec_Value.column_value; END LOOP; --returnValue := LTRIM(tmp_vStr,'_'); --returnValue := LTRIM(tmp_vStr,'、'); returnValue := SUBSTRB(LTRIM(tmp_vStr, '、'), 1, 4000); RETURN ODCIConst.Success; END; END; / CREATE OR REPLACE FUNCTION ConnStr(input VARCHAR2) RETURN VARCHAR2 PARALLEL_ENABLE AGGREGATE USING STR_CONN_TYPE; /
当然,这样一来,在实际数据长度超过4000的时候,就得不到业务需求的结果了
我也测试了原先的fun_get_Repeal_CompanyName的做法
基于同样的原因,这种做法在在实际数据长度超过4000的时候也是会报错的
我想,在使用varchar型的返回值的函数实现这个业务的时候,这种现象是不可避免的
所以,oracle的解决办法可能就是使用clob类型的返回值来实现这个函数
这一点目前还尚待证实
不过,使用clob返回值的话,java端取数据的时候就要麻烦不少了
6 楼
chenhj520
2008-04-16
to: armorking
那个自定义聚集函数,是用pl/sql写的,
可以在group by 语句中直接把它当作SUM,MIN之类的函数一样使用
我曾经测试过,应该是好使的
我使用别一种方法把问题解决了.
根据你提交的聚集函数的方法.
测试时去掉多余的字段
我在执行语句测试时,一个审批单对应有63个包.使用分组和自定义的聚函数的产生的
ORA-06052:PL/SQL :数据字或值错误:字符串缓冲区太小.
ORA-O6512:在BID.STR_CONN_TYPE,line 47
在47行代码是
tmp_vStr VARCHAR2(4000)定义为最大值.
其聚集函数为你提供的函数.
那个自定义聚集函数,是用pl/sql写的,
可以在group by 语句中直接把它当作SUM,MIN之类的函数一样使用
我曾经测试过,应该是好使的
我使用别一种方法把问题解决了.
根据你提交的聚集函数的方法.
测试时去掉多余的字段
select distinct br.repeal_id, ConnStr(pbp.package_name) from be_t_repeal br, be_t_repeal_package brp, be_t_project_detail bpd, pa_t_bid_package pbp, pa_t_bid_object pbo, be_t_providers bp, be_t_repeal_package btr, BE_T_FLOW_LOG BTFL where br.repeal_id = brp.repeal_id and brp.project_device_id = bpd.project_device_id and bpd.bid_package_id = pbp.bid_package_id and pbp.bid_object_id = pbo.bid_object_id and brp.provider_id = bp.provider_id and br.repeal_id = btr.repeal_id and br.repeal_id = btfl.repeal_id and btfl.flow_type = 1 and br.project_id = 990000000000003243 group by br.repeal_id
我在执行语句测试时,一个审批单对应有63个包.使用分组和自定义的聚函数的产生的
ORA-06052:PL/SQL :数据字或值错误:字符串缓冲区太小.
ORA-O6512:在BID.STR_CONN_TYPE,line 47
在47行代码是
tmp_vStr := tmp_vStr || '、' || rec_Value.column_value;
tmp_vStr VARCHAR2(4000)定义为最大值.
其聚集函数为你提供的函数.
5 楼
armorking
2008-04-16
chenhj520 写道
to:armorking
非常感谢你的建议.
请问你是用的pl/sql吗?
能否告诉我pl/sql的代码格式的怎么设置,谢谢!
关于你提出的哪个方案,我也想过.主要这个也是跟我们使用的平台有关.我使用的powerbos平台,这个平台在可以直接在写sql语句就可以实现所有功能.增删改查.基本上不需要写一点代码.呵呵,但平台还有些缺点.复杂的业务还是得自己写代码.
非常感谢你的建议.
请问你是用的pl/sql吗?
能否告诉我pl/sql的代码格式的怎么设置,谢谢!
关于你提出的哪个方案,我也想过.主要这个也是跟我们使用的平台有关.我使用的powerbos平台,这个平台在可以直接在写sql语句就可以实现所有功能.增删改查.基本上不需要写一点代码.呵呵,但平台还有些缺点.复杂的业务还是得自己写代码.
那个自定义聚集函数,是用pl/sql写的,
可以在group by 语句中直接把它当作SUM,MIN之类的函数一样使用
我曾经测试过,应该是好使的
至于pl/sql代码的格式设置
我是做了一个sql整形用的java函数
/* * @(#) SQLStringFormatter.java 2005-09-14 */ package org.ibatis.helper.common.util; import java.util.HashMap; import java.util.HashSet; import java.util.Map; import java.util.Set; import java.util.Stack; import org.ibatis.helper.common.util.ConstantMark; import org.ibatis.helper.common.util.StringCheckUtil; /** * SQL文の書式変換用 * @author LIANGZHI ZHU * @since JDK1.4 * $Date: 2005-09-14 13:01:33 $ */ public class SQLStringFormatter { private static Class clazz = SQLStringFormatter.class; public static String formatSQLString(String sqlString) { String strSrc = toUpperCaseExceptConst(sqlString); strSrc = strSrc.replaceAll("\t" , " "); strSrc = strSrc.replaceAll("SELECT " , "SELECT \n"); strSrc = strSrc.replaceAll(" \\(" , " \n\\(\n "); strSrc = strSrc.replaceAll(" \\) " , " \n\\) \n"); strSrc = strSrc.replaceAll("," , ", \n"); strSrc = strSrc.replaceAll(" VALUES " , "\nVALUES \n"); strSrc = strSrc.replaceAll(" FROM " , "\nFROM \n"); strSrc = strSrc.replaceAll(" SET " , "\nSET \n"); strSrc = strSrc.replaceAll(" LEFT " , "\nLEFT "); strSrc = strSrc.replaceAll(" INNER " , "\nINNER "); strSrc = strSrc.replaceAll(" ON " , " ON\n"); strSrc = strSrc.replaceAll(" WHERE " , "\nWHERE "); strSrc = strSrc.replaceAll(" AND " , "\nAND "); strSrc = strSrc.replaceAll(" OR " , "\nOR "); strSrc = strSrc.replaceAll(" UNION " , "\nUNION\n"); strSrc = strSrc.replaceAll(" ORDER " , "\nORDER "); strSrc = strSrc.replaceAll(" GROUP " , "\nGROUP "); //strSrc = strSrc.replaceAll(" BY " , " BY \n"); strSrc = strSrc.replaceAll("\n\n" , "\n"); //StepTimeStampUtil.logTimeStamp(clazz); Stack stack = new Stack(); boolean additionalIndentFlg = false; StringBuffer sb = new StringBuffer(strSrc.length()); String[] lineArray = strSrc.split("\n"); for (int i = 0 ; i < lineArray.length ; i++) { String line = lineArray[i]; if (line == null ){ continue; } line = line.trim(); if (line.length() == 0 ){ continue; } int level = stack.size(); if (line.indexOf("(") != -1 ){ stack.push("("); } int indexRight = line.indexOf(")"); if (indexRight != -1 ){ stack.pop(); if (indexRight == 0 ){ level--; } } if (containsKeyword(line, "FROM") ){ additionalIndentFlg = false; } if (additionalIndentFlg ){ level++; } sb.append(createIndentByLevel(level)); sb.append(line).append("\n"); if (containsKeyword(line, "SELECT") ){ additionalIndentFlg = true; } } //StepTimeStampUtil.logTimeStamp(clazz); return sb.toString(); } //Set<String 分割マーク> private static Set DIVISION_MARK_SET; static { DIVISION_MARK_SET = new HashSet(); DIVISION_MARK_SET.add(" "); DIVISION_MARK_SET.add("("); DIVISION_MARK_SET.add(")"); DIVISION_MARK_SET.add("\t"); DIVISION_MARK_SET.add("\r"); DIVISION_MARK_SET.add("\n"); } private static boolean containsKeyword(String str, String keyword) { if (StringCheckUtil.isEmpty(keyword) || StringCheckUtil.isEmpty(str) ){ return false; } int index = str.indexOf(keyword); if (index == -1 ){ return false; } if (index > 0 && !DIVISION_MARK_SET.contains(String.valueOf(str.charAt(index - 1))) ){ return false; } int keywordLength = keyword.length(); if (index < str.length() - 1 - keywordLength && !DIVISION_MARK_SET.contains(String.valueOf(str.charAt(index + keywordLength + 1))) ){ return false; } return true; } //Map<Integer level, String indentStr> private static Map INDENT_MAP = new HashMap(); private static String createIndentByLevel(int levelValue) { Integer level = Integer.valueOf(String.valueOf(levelValue)); if (INDENT_MAP.containsKey(level) ){ return (String)INDENT_MAP.get(level); } //String indentStr = StringUtils.leftPad("", level.intValue() * 4, ConstantMark.CHAR_SPACE); int len = level.intValue() * 4; StringBuffer sb = new StringBuffer(len); for (int i = 0 ; i < len ; i++) { sb.append(ConstantMark.SPACE_CHAR); } String indentStr = sb.toString(); synchronized(clazz) { INDENT_MAP.put(level, indentStr); } return indentStr; } private static String toUpperCaseExceptConst(String str) { if (StringCheckUtil.isTrimedEmpty(str) ){ return str; } StringBuffer sb = new StringBuffer(); String[] strArray = str.split(ConstantMark.SINGLE_QUOTAION); for (int i = 0 ; i < strArray.length ; i++) { sb.append((i > 0) ? ConstantMark.SINGLE_QUOTAION : ConstantMark.BLANK); String line = StringCheckUtil.nvl(strArray[i]); if ((i % 2 == 0) ){ line = trimSpace2One(line.toUpperCase()); } sb.append(line); } return sb.toString(); } private static String trimSpace2One(String str) { if (StringCheckUtil.isEmpty(str) ){ return str; } StringBuffer sb = new StringBuffer(); char[] charArray = str.toCharArray(); boolean spaceStartFlg = false; for (int i = 0 ; i < charArray.length ; i++) { if (charArray[i] == ConstantMark.SPACE_CHAR || charArray[i] == ConstantMark.FULL_SPACE_CHAR || charArray[i] == ConstantMark.TAB_CHAR ){ spaceStartFlg = true; continue; } if (spaceStartFlg ){ sb.append(ConstantMark.SPACE_CHAR); spaceStartFlg = false; } sb.append(charArray[i]); } if (spaceStartFlg ){ sb.append(ConstantMark.SPACE_CHAR); } return sb.toString(); } public static void main(String[] args) { String sqlString = "select distinct pbp.package_name,pbp.package_order,pbp.child_order from be_t_repeal br, be_t_repeal_package brp, be_t_project_detail bpd, pa_t_bid_package pbp, pa_t_bid_object pbo, be_t_providers bp where br.repeal_id = brp.repeal_id and brp.project_device_id = bpd.project_device_id and bpd.bid_package_id = pbp.bid_package_id and pbp.bid_object_id = pbo.bid_object_id and brp.provider_id = bp.provider_id and br.repeal_id = p_repeal_id order by pbp.package_order||pbp.child_order,pbp.child_order,pbp.package_name"; System.out.println(formatSQLString(sqlString)); } }
package org.ibatis.helper.common.util; /** * @author zhu liangzhi * @date 2007/03/07 * * Mark Contants */ public class ConstantMark { private ConstantMark(){} //private contructor public static final String BLANK = ""; public static final String PERIOD = "."; public static final String COLON = ":"; public static final String SEMICOLON = ";"; public static final String SHARP = "#"; public static final String DOLLAR = "$"; public static final String UNDER_BAR = "_"; public static final String TAB = "\t"; public static final String LINE_FEED = "\n"; public static final String SLASH = "/"; public static final String SPACE = " "; public static final String SINGLE_QUOTAION = "'"; //丸括弧 public static final String ROUND_BRACKET_LEFT = "("; public static final String ROUND_BRACKET_RIGHT = ")"; //山形括弧 public static final String ANGLE_BRACKET_LEFT = "<"; public static final String ANGLE_BRACKET_RIGHT = ">"; //中括弧 public static final String BRACE_LEFT = "{"; public static final String BRACE_RIGHT = "}"; public static final char SLASH_CHAR = '/'; public static final char SPACE_CHAR = ' '; public static final char FULL_SPACE_CHAR = ' '; public static final char TAB_CHAR = '\t'; //シングルクォーテーション public static final char SINGLE_QUOTAION_CHAR = '\''; }
/* * 作成日: 2007/03/23 */ package org.ibatis.helper.common.util; import java.util.HashSet; import java.util.Iterator; import java.util.Set; /** * @author zhu liangzhi * * Stringに関するチェック処理用 */ public class StringCheckUtil { ////////////////////////////////////////////////////////// //Properties private static Set BOOLEAN_VALUE_SET; ////////////////////////////////////////////////////////// //static static { BOOLEAN_VALUE_SET = new HashSet(); BOOLEAN_VALUE_SET.add("true"); BOOLEAN_VALUE_SET.add("false"); } ////////////////////////////////////////////////////////// //public static method public static boolean isNull(String str) { return str == null; } public static boolean isEmpty(String str) { return isNull(str) || str.length() == 0; } public static boolean isTrimedEmpty(String str) { return isNull(str) || str.trim().length() == 0; } public static String nvl(String str) { return isNull(str) ? "" : str; } public static boolean isBooleanType(String str) { return !isEmpty(str) && BOOLEAN_VALUE_SET.contains(str.toLowerCase()) ; } public static boolean isPermitted(Set permittedValueSet, String value) { if (value == null || value.length() == 0 || permittedValueSet == null || permittedValueSet.size() == 0 ){ return true; } int limit = 0; for (Iterator i = permittedValueSet.iterator() ; i.hasNext() ; ) { String permittedValue = (String)i.next(); int permittedValueLength = (permittedValue == null) ? 0 : permittedValue.length(); limit = (permittedValueLength > limit) ? permittedValueLength : limit; } if (limit == 0 ){ return true; } value = value.toUpperCase(); int valueLength = value.length(); StringBuffer sb = new StringBuffer(); for (int i = 0 ; i < valueLength ; i++) { sb.append(value.charAt(i)); if (permittedValueSet.contains(sb.toString()) ){ sb = new StringBuffer(); continue; } if (sb.length() >= limit || i == valueLength - 1 ){ return false; } } return true; } }
不过这个sql整形程序还不是很完善,有时候还需要在生成结果的基础上作些调整
4 楼
chenhj520
2008-04-16
to:armorking
非常感谢你的建议.
请问你是用的pl/sql吗?
能否告诉我pl/sql的代码格式的怎么设置,谢谢!
关于你提出的哪个方案,我也想过.主要这个也是跟我们使用的平台有关.我使用的powerbos平台,这个平台在可以直接在写sql语句就可以实现所有功能.增删改查.基本上不需要写一点代码.呵呵,但平台还有些缺点.复杂的业务还是得自己写代码.
非常感谢你的建议.
请问你是用的pl/sql吗?
能否告诉我pl/sql的代码格式的怎么设置,谢谢!
关于你提出的哪个方案,我也想过.主要这个也是跟我们使用的平台有关.我使用的powerbos平台,这个平台在可以直接在写sql语句就可以实现所有功能.增删改查.基本上不需要写一点代码.呵呵,但平台还有些缺点.复杂的业务还是得自己写代码.
3 楼
chenhj520
2008-04-16
语句太长了...
找到了解决方法.但这个问题不是知道可能是oracle的查询语句问题.
我在函数fun_get_Repeal_package中加入一些输出信息如:
这个函数直接放在查询语中时执行非常慢.
output结果:
2008.04.16 16:54:43
2008.04.16 16:54:43
2008.04.16 16:54:43
2008.04.16 16:54:43
2008.04.16 16:54:43
2008.04.16 16:54:43
2008.04.16 16:54:43
2008.04.16 16:54:43
2008.04.16 16:54:43
2008.04.16 16:54:43
2008.04.16 16:54:43
2008.04.16 16:54:43
2008.04.16 16:54:43[align=left][/align]
2008.04.16 16:54:43
2008.04.16 16:54:43
....
其输出信息已经超出我设置的output buffer size 26000的大小
并且报0ra-200:ORM-10027 :buffer overflow,limit of 26000 bytes
ORA-06512: 在"SYS.DBMS_OUTPUT" ,line 32
ORA-06512: 在"SYS.DBMS_OUTPUT" ,line 97
ORA-06512: 在"SYS.DBMS_OUTPUT" ,line 112
只有两条数据怎么会执行哪么多.真是奇怪.我个人认为,可能是有可能在与其它每个表关联时他会产生许多重复的数据,大量的重复数据每次都会去执行哪几个函数.
为了证实我的这个想法.我同样的两条数据使用单表执行.
测试结果0.063秒就完成
其结果并不慢,原因所在找到了.问题就有解决的方法:
在Sql语句最后一层外包一层.
如果大家有遇到同样的问题可以这样解决.
呵呵,超长的语句.
找到了解决方法.但这个问题不是知道可能是oracle的查询语句问题.
我在函数fun_get_Repeal_package中加入一些输出信息如:
create or replace function fun_get_Repeal_package(p_repeal_id varchar) return varchar as cursor cur is select distinct pbp.package_name, pbp.package_order, pbp.child_order from be_t_repeal br, be_t_repeal_package brp, be_t_project_detail bpd, pa_t_bid_package pbp pa_t_bid_object pbo, --be_t_providers bp where br.repeal_id = brp.repeal_id and brp.project_device_id = bpd.project_device_id and bpd.bid_package_id = pbp.bid_package_id and pbp.bid_object_id = pbo.bid_object_id and brp.provider_id = bp.provider_id and br.repeal_id = p_repeal_id order by pbp.package_order || pbp.child_order, pbp.child_order, pbp.package_name; v_package varchar2(1000); begin v_package := ''; dbms_output.put_line(to_char(new_time(sysdate, 'PDT', 'GMT'), 'yyyy.mm.dd hh24:mi:ss')); for cur_repeal in cur loop v_package := v_package || cur_repeal.package_name || '、'; end loop; --输出两这函数的执行的时间 dbms_output.put_line(to_char(new_time(sysdate, 'PDT', 'GMT'), 'yyyy.mm.dd hh24:mi:ss')); v_package := substr(v_package, 1, length(v_package) - 1); return v_package; end;
这个函数直接放在查询语中时执行非常慢.
output结果:
2008.04.16 16:54:43
2008.04.16 16:54:43
2008.04.16 16:54:43
2008.04.16 16:54:43
2008.04.16 16:54:43
2008.04.16 16:54:43
2008.04.16 16:54:43
2008.04.16 16:54:43
2008.04.16 16:54:43
2008.04.16 16:54:43
2008.04.16 16:54:43
2008.04.16 16:54:43
2008.04.16 16:54:43[align=left][/align]
2008.04.16 16:54:43
2008.04.16 16:54:43
....
其输出信息已经超出我设置的output buffer size 26000的大小
并且报0ra-200:ORM-10027 :buffer overflow,limit of 26000 bytes
ORA-06512: 在"SYS.DBMS_OUTPUT" ,line 32
ORA-06512: 在"SYS.DBMS_OUTPUT" ,line 97
ORA-06512: 在"SYS.DBMS_OUTPUT" ,line 112
只有两条数据怎么会执行哪么多.真是奇怪.我个人认为,可能是有可能在与其它每个表关联时他会产生许多重复的数据,大量的重复数据每次都会去执行哪几个函数.
为了证实我的这个想法.我同样的两条数据使用单表执行.
select l.*,fun_get_repeal_package(l.repeal_id),fun_get_repeal_companyname(l.repeal_id) from be_t_repeal l where l.repeal_id in (990000000000001761,990000000000001741)
测试结果0.063秒就完成
其结果并不慢,原因所在找到了.问题就有解决的方法:
在Sql语句最后一层外包一层.
select tt.* ,fun_get_repeal_package(tt.repeal_id),fun_get_repeal_companyname(tt.repeal_id),fun_get_repeal_reason(tt.repeal_id) from 上面复杂的sql去掉里面几个函数 ) tt
如果大家有遇到同样的问题可以这样解决.
呵呵,超长的语句.
2 楼
armorking
2008-04-16
先整形
这样看就容易多了
问题的原因很简单
因为FUN_GET_REPEAL_PACKAGE、FUN_GET_REPEAL_COMPANYNAME函数的做法有性能问题
在查询语句中调用它就相当于子查询
解决办法有两个,
1、把原来的sql语句改写成非distinct的形式,把字符串拼接处理放到java程序中
2、用oracle自定义聚集函数的形式改写FUN_GET_REPEAL_PACKAGE、FUN_GET_REPEAL_COMPANYNAME函数
把distinct形式的sql改写成group形式即可
改写函数的时候,请参照下面的函数实现
SELECT DISTINCT BR.REPEAL_ID, TO_CHAR(BR.CREATE_DATE,'yyyy-MM-dd hh24:mi') AS CREATE_DATE, PBO.OBJECT_ALIAS_NAME OBJECTNAME, FUN_GET_REPEAL_PACKAGE(BR.REPEAL_ID) PACKAGENAME, BR.IS_AUDIT, FUN_GET_REPEAL_COMPANYNAME(BR.REPEAL_ID) COMPANYNAME, ( SELECT USER_NAME FROM SM_T_USER WHERE USER_ID = BR.CREATE_USER_ID ) USER_NAME, CASE BR.IS_GROUP_REPORT WHEN 2 THEN 'AAA' WHEN 1 THEN 'BBB' WHEN 0 THEN 'CCC' END AS IS_TYPE, BR.OBJECT_NUMBER, BPD.PROJECT_ID, BR.REPEAL_STATUS, ( SELECT STU.USER_NAME FROM BE_T_FLOW_LOG BTF, SM_T_USER STU WHERE BTF.SUB_USER_ID = STU.USER_ID AND BR.REPEAL_STATUS = BTF.BILLSTATUS AND BR.REPEAL_ID = BTF.REPEAL_ID AND BTF.FLOW_ABLE <> -1 AND ROWNUM = 1 ) RUSER_NAME, BR.CREATE_USER_ID, BR.IS_GROUP_REPORT, CASE WHEN ( ( SELECT COUNT(*) FROM BE_T_FLOW_LOG BTW WHERE BTW.FLOW_ABLE = 0 AND BTW.REPEAL_ID = BR.REPEAL_ID AND BTW.BILLSTATUS = 3 AND BTW.AUDIT_STATUS IS NULL AND ( ( SELECT COUNT(*) FROM BE_T_FLOW_LOG BTLG WHERE BTLG.FLOW_ABLE = -1 AND BTLG.REPEAL_ID = BR.REPEAL_ID ) > 0 ) ) > 0 ) THEN 'red' ELSE '' END AS COLOR, 'a' INDEXNO, BR.BLANK_OUT, FUN_GET_REPEAL_REASON(BR.REPEAL_ID) REPEAL_REASON FROM BE_T_REPEAL BR, BE_T_REPEAL_PACKAGE BRP, BE_T_PROJECT_DETAIL BPD, PA_T_BID_PACKAGE PBP, PA_T_BID_OBJECT PBO, BE_T_PROVIDERS BP, BE_T_REPEAL_PACKAGE BTR, BE_T_FLOW_LOG BTFL WHERE BR.REPEAL_ID = BRP.REPEAL_ID AND BRP.PROJECT_DEVICE_ID = BPD.PROJECT_DEVICE_ID AND BPD.BID_PACKAGE_ID = PBP.BID_PACKAGE_ID AND PBP.BID_OBJECT_ID = PBO.BID_OBJECT_ID AND BRP.PROVIDER_ID = BP.PROVIDER_ID AND BR.REPEAL_ID = BTR.REPEAL_ID AND BR.REPEAL_ID = BTFL.REPEAL_ID AND BTFL.FLOW_TYPE = 1 AND BR.PROJECT_ID = 990000000000003243
create or replace function fun_get_Repeal_package( p_repeal_id varchar ) return varchar as cursor cur is SELECT DISTINCT PBP.PACKAGE_NAME, PBP.PACKAGE_ORDER, PBP.CHILD_ORDER FROM BE_T_REPEAL BR, BE_T_REPEAL_PACKAGE BRP, BE_T_PROJECT_DETAIL BPD, PA_T_BID_PACKAGE PBP, PA_T_BID_OBJECT PBO, BE_T_PROVIDERS BP WHERE BR.REPEAL_ID = BRP.REPEAL_ID AND BRP.PROJECT_DEVICE_ID = BPD.PROJECT_DEVICE_ID AND BPD.BID_PACKAGE_ID = PBP.BID_PACKAGE_ID AND PBP.BID_OBJECT_ID = PBO.BID_OBJECT_ID AND BRP.PROVIDER_ID = BP.PROVIDER_ID AND BR.REPEAL_ID = P_REPEAL_ID ORDER BY PBP.PACKAGE_ORDER||PBP.CHILD_ORDER, PBP.CHILD_ORDER, PBP.PACKAGE_NAME ; v_package varchar2(1000); begin v_package := ''; for cur_repeal in cur loop v_package := v_package || cur_repeal.package_name || '、'; end loop; v_package := substr(v_package, 1, length(v_package) - 1); return v_package; end;
这样看就容易多了
问题的原因很简单
因为FUN_GET_REPEAL_PACKAGE、FUN_GET_REPEAL_COMPANYNAME函数的做法有性能问题
在查询语句中调用它就相当于子查询
解决办法有两个,
1、把原来的sql语句改写成非distinct的形式,把字符串拼接处理放到java程序中
2、用oracle自定义聚集函数的形式改写FUN_GET_REPEAL_PACKAGE、FUN_GET_REPEAL_COMPANYNAME函数
把distinct形式的sql改写成group形式即可
改写函数的时候,请参照下面的函数实现
--自定義集約関数→SORTED CREATE OR REPLACE TYPE VcArrayType IS TABLE OF VARCHAR2(4000); / CREATE OR REPLACE TYPE STR_CONN_TYPE AS OBJECT ( --vStr VARCHAR2(4000), vStr VcArrayType, STATIC FUNCTION ODCIAggregateInitialize(sctx IN OUT STR_CONN_TYPE ) RETURN NUMBER, MEMBER FUNCTION ODCIAggregateIterate(SELF IN OUT STR_CONN_TYPE , VALUE IN VARCHAR2 ) RETURN NUMBER, MEMBER FUNCTION ODCIAggregateMerge(SELF IN OUT STR_CONN_TYPE, ctx2 IN STR_CONN_TYPE) RETURN NUMBER, MEMBER FUNCTION ODCIAggregateTerminate(SELF IN STR_CONN_TYPE, returnValue OUT VARCHAR2, flags IN NUMBER) RETURN NUMBER ); / CREATE OR REPLACE TYPE BODY STR_CONN_TYPE IS STATIC FUNCTION ODCIAggregateInitialize(sctx IN OUT STR_CONN_TYPE) RETURN NUMBER IS BEGIN --sctx := STR_CONN_TYPE(NULL); sctx := STR_CONN_TYPE(VcArrayType()); RETURN ODCIConst.Success; END; MEMBER FUNCTION ODCIAggregateIterate(SELF IN OUT STR_CONN_TYPE, VALUE IN VARCHAR2 ) RETURN NUMBER IS BEGIN --SELF.vStr := SELF.vStr || ';' || VALUE; vStr.EXTEND; vStr(vStr.COUNT) := VALUE; RETURN ODCIConst.Success; END; MEMBER FUNCTION ODCIAggregateMerge(SELF IN OUT STR_CONN_TYPE, ctx2 IN STR_CONN_TYPE) RETURN NUMBER IS BEGIN RETURN ODCIConst.Success; END; MEMBER FUNCTION ODCIAggregateTerminate(SELF IN STR_CONN_TYPE, returnValue OUT VARCHAR2, flags IN NUMBER) RETURN NUMBER IS tmp_vStr VARCHAR2(4000); BEGIN --returnValue := LTRIM(SELF.vStr,';'); FOR rec_Value IN ( SELECT column_value FROM TABLE(vStr) --ORDER BY to_number(column_value) ORDER BY column_value ) LOOP --tmp_vStr := tmp_vStr || '_' || rec_Value.column_value; tmp_vStr := tmp_vStr || '、' || rec_Value.column_value; END LOOP; --returnValue := LTRIM(tmp_vStr,'_'); returnValue := LTRIM(tmp_vStr,'、'); RETURN ODCIConst.Success; END; END; / CREATE OR REPLACE FUNCTION ConnStr(input VARCHAR2) RETURN VARCHAR2 PARALLEL_ENABLE AGGREGATE USING STR_CONN_TYPE; /
1 楼
LucasLee
2008-04-16
看上去这么乱呢,你的分析还不够,我还是懒得仔细看了
相关推荐
文章讨论了当前小学语数专业中问题设计的应用现状,并对存在的问题进行了深入分析,提出了一系列创新的教学方法,目的是提高教学效率并促进学生综合能力的发展。 首先,文章指出了在小学教学中,问题设计的重要性。...
传统的机械设计方法虽然能合理选择差速器和半轴中的齿轮、轴等零件,但这一过程通常伴随着设计周期长、效率低和复杂性高的问题。为了解决这些问题,本研究探讨了利用MATLAB软件对45吨铰接式自卸车差速器进行最优化...
这提示需求分析员在与高层交流时,应着重于讨论存在的问题和潜在的机会。 **SERU诫语2-7**:对于面向用户的嵌入式系统,行为分析是要点。这类系统的设计需要特别关注用户体验,确保系统操作符合用户期望。 **SERU...
zip》是一个关于大数据技术应用的文档,详细阐述了在知名互联网公司——美团中,如何构建和优化一个高效、稳定且可扩展的大数据处理平台。该文档由资深工程师谢语宸撰写,融合了丰富的实践经验和深入的技术洞察,为...
在智能手机领域,众多品牌和型号的手机犹如繁星般点缀着市场,而语信E60正是其中一颗较为低调的星。尽管不如大品牌手机那样广为人知,但它依然拥有一群忠实的用户群体。对于这些用户来说,为语信E60找到合适的驱动...
6. **停车收费的争议与智慧化**:停车费的定价和管理是一个复杂问题,既要考虑市场机制,也要防止乱收费,智慧停车系统应能实现明码标价和适时调整。 7. **智慧停车对城市交通的影响**:智慧停车系统不仅能够方便...
本文提出了一种基于深度神经网络的维吾尔语语音识别方法,并对其进行了实验和优化。本研究结果表明,深度神经网络模型可以显著提高语音识别率,并具有广阔的应用前景。 知识点: 1. 深度神经网络(Deep Neural ...
深度学习是指通过复杂的思维活动进行深入学习的过程,它能够促使学习者达到对知识深层理解,并在真实情境中解决复杂问题的能力。在初中数学教学中,深度学习表现为引导学生自主探究和合作探究,鼓励学生独立发现、...
在生物识别技术中,语者确认是一个重要的应用领域,它通过分析语音信号的特性来验证说话者的身份。 **1.1 语者识别的概念** 语者识别系统的核心是通过分析语音信号来确定说话人的身份。这种技术利用了每个人的语音...
综上所述,多信道接收机中语用网格码的卷积译码器的网格去映象器是一个涉及编码理论、信道模型、优化算法和硬件实现等多个领域的综合性问题。通过深入理解和优化这一组件,我们可以显著提升无线通信系统的整体性能,...
这种变换技巧在数学的许多领域中都极为关键,例如在微积分中求导和积分时,适当的变量替换能简化问题,使复杂问题迎刃而解。学生需要掌握此类变换的规则与技巧,以达到举一反三的效果。 多项式展开是数学中的基本...
假设我们有一个数据源,例如一个列表或数据库,我们需要在事件处理程序中编写查询逻辑: ```csharp private void textBox1_TextChanged(object sender, EventArgs e) { string searchText = textBox1.Text.Trim();...
内容概要:本文围绕DeepSeek这一国产开源的通用人工智能(AGI)推理模型展开讨论。介绍了DeepSeek及其开源推理模型DeepSeek-R1的特点和优势,强调其能够处理复杂任务和免费商用的价值。主要内容包括DeepSeek的功能...
RDMA参数选择是一个复杂的问题,需要考虑多种参数的组合。通过本文的讨论,我们希望能够帮助读者更好地理解RDMA参数选择的重要性,并提供了一些实用的建议来优化RDMA参数选择。 在RDMA技术中,还有一些其他的技术...
您可以利用ChatGPT设计小组活动,如:“设计一个团队项目,让学生共同解决一个与[主题]相关的问题。”这将促进团队合作,增强学生之间的沟通技巧。 综上所述,ChatGPT不仅是一种工具,更是教学创新的催化剂。通过...
lingo软件是解决数学优化问题的常用工具,本文将从 lingua Seeker 的使用技巧出发,讨论 lingo 软件在数学建模和求解中的应用。 一、 lingua Seeker 的使用技巧 lingua Seeker 是一种数学建模语言,用于描述和求解...
本文专注于对比分析英汉应用语言学实证性论文中模糊限制语的使用频率和分布特征,主要涵盖引言、方法、结果和讨论四个部分。 一、背景与重要性 英语作为全球学术交流的主要语言,其熟练运用对于国际研究者至关重要...
Matlab基于VQ的语者识别系统是一种用于判断说话者身份的技术,它涉及到语音信号处理、模式识别和机器学习等多个领域的知识。该系统的核心在于使用矢量量化(Vector Quantization,VQ)算法对语音特征参数进行编码和...
这篇文档是四川省成都外国语学校2019届高三下学期3月份的一份数学理科月考试题,包含了选择题、填空题和解答题三个部分,共计12道选择题、4道填空题和若干道解答题。题目涵盖了复数、反证法、不等式、等差数列、平面...