浏览 383 次
|
精华帖 (0) :: 良好帖 (0) :: 新手帖 (0) :: 隐藏帖 (0)
|
|
|---|---|
| 作者 | 正文 |
|
时间:2008-04-16
一条查询语句中包括有多个函数,函数的作用主要是主组合字符串.两个数据查询出来花了快一分多钟.
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秒. 能提供的点优化思路吗?谢谢各位了 声明:JavaEye文章版权属于作者,受法律保护。没有作者书面许可不得转载。
推荐链接
|
|
| 返回顶楼 | |
|
时间:2008-04-16
看上去这么乱呢,你的分析还不够,我还是懒得仔细看了
|
|
| 返回顶楼 | |
|
时间:2008-04-16
先整形
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;
/
|
|
| 返回顶楼 | |
|
时间:2008-04-16
语句太长了...
找到了解决方法.但这个问题不是知道可能是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 如果大家有遇到同样的问题可以这样解决. 呵呵,超长的语句. |
|
| 返回顶楼 | |
|
时间:2008-04-16
to:armorking
非常感谢你的建议. 请问你是用的pl/sql吗? 能否告诉我pl/sql的代码格式的怎么设置,谢谢! 关于你提出的哪个方案,我也想过.主要这个也是跟我们使用的平台有关.我使用的powerbos平台,这个平台在可以直接在写sql语句就可以实现所有功能.增删改查.基本上不需要写一点代码.呵呵,但平台还有些缺点.复杂的业务还是得自己写代码. |
|
| 返回顶楼 | |
|
时间:2008-04-16
chenhj520 写道 to:armorking
非常感谢你的建议. 请问你是用的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整形程序还不是很完善,有时候还需要在生成结果的基础上作些调整 |
|
| 返回顶楼 | |
|
时间:2008-04-16
to: armorking
那个自定义聚集函数,是用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)定义为最大值. 其聚集函数为你提供的函数. |
|
| 返回顶楼 | |
|
时间: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端取数据的时候就要麻烦不少了 |
|
| 返回顶楼 | |
|
时间:2008-04-17
用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;
/
|
|
| 返回顶楼 | |





