问题描述
输入参数是2个以逗号分隔的id(from_id和to_id)。运行报告时,必须对每个ID进行评估。 From_id ='202031,202032,202035,202041,...' To_id ='202111,202112,202135,202141,...' 应该从_id过滤每个记录,并在打印到日志文件时打印相应的to_id。始终为202031至202111、202032至202112、202035至202135、20241至202141。以下是预期结果。
Num_ber Description person_id person_name Rolled_To_term From_id to_id term_priority_to_term max_amt_to_term
90010001 fund1 1 abc N 202031 202111 3 23
90010001 fund1 1 abc N 202032 202112 6 110
50010001 fund2 2 xyz N 202035 202135 2 45
50010001 fund2 3 efg N 202035 202135 5 50
以下过程将更新to_id,但from_id仍为202031并再次循环。光标不筛选其他frm_id。
PROCEDURE report_v1 (
p_frm_id_list VARCHAR2,p_to_id_list VARCHAR2
) AS
exemp_log_file utl_file.file_type;
log_msg VARCHAR2(600);
frm_id_list VARCHAR2(50);
frm_id_list_temp VARCHAR2(50);
frm_id VARCHAR2(50);
to_id_list VARCHAR2(50);
to_id_list _temp VARCHAR2(50);
to_id VARCHAR2(50);
CURSOR get_expt_info_c IS
SELECT
code AS num_ber,desc AS description,a.term_expiration AS exp_term,(select p_id from tab3 c where a.id=c.id) as person_id,(select p_name from tab3 c where a.id=c.id) as person_name,a.term_code AS from_id,nvl(
(
SELECT disTINCT
'Y'
FROM
tab2 b
WHERE
b.term_code = to_term
AND b.id = a.id
),'N'
) rolled_to_term,a.priority AS term_priority_to_term,a.amount AS max_amt_to_term
FROM
tab left
JOIN tab2 a ON code = a.code
AND term_code = a.term_code
WHERE
instr(
frm_id,a.term_code
) > 0;
BEGIN
exemp_log_file := utl_file.fopen(dir,'report.csv','w');
log_msg := 'Report header';
utl_file.put_line(exemp_log_file,log_msg,autoflush => true );
frm_id_list := replace(p_frm_id_list,' ','');
to_id_list := replace( p_ to_id_list,'' );
WHILE frm_id_list IS NOT NULL LOOP
IF instr( frm_id_list,',') > 0 THEN
frm_id := substr(frm_id_list,1,instr(frm_id_list,') - 1 );
frm_id_list_temp := substr(frm_id_list,' ) + 1);
ELSE
frm_id := frm_id_list;
frm_id_list_temp := NULL;
END IF;
frm_id_list := frm_id_list_temp;
WHILE to_id_list IS NOT NULL LOOP
IF instr(to_id_list,' ) > 0 THEN
to_id := substr(to_id_list,instr(to_id_list,' ) - 1 );
to_id_list_temp := substr(to_id_list,' ) + 1 );
ELSE
to_id := to_id_list;
to_id_list_temp := NULL;
END IF;
to_id_list := to_id_list_temp;
FOR exemp IN get_expt_info_c LOOP
utl_file.put_line(
exemp_log_file,exemp.num_ber
|| ';'
|| exemp.description
|| ';'
|| exemp.exp_term
|| ';'
|| exemp.person_id
|| ';'
|| exemp.person_name
|| ';'
|| exemp.from_id
|| ';'
|| exemp.rolled_to_term
|| ';'
|| exemp.priority
|| ';'
|| exemp.amt
|| ';'
|| to_id,autoflush => true
);
END LOOP;
END LOOP;
END LOOP;
EXCEPTION
WHEN no_data_found THEN
NULL;
WHEN OTHERS THEN
EXIT;
utl_file.fclose(exemp_log_file);
END report_v1;
表定义和样本数据
CREATE TABLE "TAB"
(CODE" VARCHAR2(8 CHAR) NOT NULL ENABLE,"TERM_CODE" VARCHAR2(6 CHAR) NOT NULL ENABLE,"DESC" VARCHAR2(30 CHAR) NOT NULL ENABLE,"DETAIL_CODE" VARCHAR2(4 CHAR) NOT NULL ENABLE,"ACTIVITY_DATE" DATE NOT NULL ENABLE
)
CODE TERM_CODE DESC DETAIL_CODE ACTIVITY_DATE
90010001 202031 fund1 aaa 09-Jun-2009
CREATE TABLE."TAB2"
("CODE" VARCHAR2(8 CHAR),"ID" NUMBER(8,0),"TERM_CODE" VARCHAR2(6 CHAR),"ACTIVITY_DATE" DATE,"TERM_EXPIRATION" VARCHAR2(6 CHAR),"PRIORITY" NUMBER(2,"AMOUNT" NUMBER(7,2)
)
CODE ID TERM_CODE ACTIVITY_DATE TERM_EXPIRATION PRIORITY AMOUNT
90010001 1 202031 09-Jun-2009 31-DEC-2030 3 23
CREATE TABLE "TAB3"
("P_ID" NUMBER(8,0) NOT NULL ENABLE,"P_NAME" VARCHAR2(60 CHAR) NOT NULL ENABLE,"ACTIVITY_DATE" DATE NOT NULL ENABLE
)
P_ID P_NAME ACTIVITY_DATE
1 abc 01-JAN-2007
任何人都可以提出一种更好的方法/替代我的方法或纠正我的程序。
解决方法
您的描述表明您正在将2个CSV字符串拆分为各自的元素,然后将拆分后的元素组合为2个元素的集合,每个字符串中一个。这可以在单个sql语句中完成:
with parms( from_ids,to_ids) as
( select '202031,202032,202035,202041','202111,202112,202135,202141'
from dual
)
select from_id,to_id
from ( select regexp_substr (from_ids,'[^,]+',1,rownum) from_id,regexp_substr (to_ids,rownum) to_id,1+length(from_ids)-length(replace(from_ids,','')) cf,1+ length(to_ids)-length(replace(to_ids,'')) ct
from parms
connect by level <= length (regexp_replace (from_ids,]+')) + 1
)
where cf=ct;
如果初始字符串不包含相同数量的元素,则查询不返回任何行。
我不确定如何处理您的过程,因为您发布的内容无效并且除了编译错误外没有产生任何其他结果。它不引用参数“ from_id_list”,但使用变量“ frm_id_list”(已定义)和“ p_from_id_list”(未定义)。至于参数“ to_id_list”,它将尝试在分配中使用它作为LVALUE。由于将其定义为IN参数,因此不允许这样做。此外,该过程不引用除“ log_msg”和“ exempt_log_file”以外的任何局部变量。看起来您是错误地发布了先前版本。您可能需要编辑问题并发布正确的版本。
但是,我确实确实发现了2个WHILE循环正在尝试执行拆分和合并过程。上面的查询替换了两者。但这如何适合游标循环?
因此,我有一个项目已经建立了一段时间,该项目与github上的这个项目几乎相同:https://github.com/DevNambi/sql-server-regex
您可能想要下载该文件,进行安装(C#确定性正则表达式功能不会破坏SQL Server),然后使用Matches获取匹配项及其值的结果集。与将允许这样的事情。
SELECT S.RelevantColumns,TRY_CONVERT(INT,Match) as ID
FROM SourceTable S
CROSS APPLY dbo.RegexMatches(S.IDlist,'(\d),') x
INNER JOIN dbo.SomeOtherTable OT
ON OT.ID = TRY_CONVERT(INT,x.Match)
当报告布局不利于像您的上方光标那样进行迭代时,我已经做了几次。让我知道是否有帮助。我完全不确定整个脚本的目的是什么,但是希望它可以对如何实现此目标提供一些见识?