遍历列表逗号分隔的参数,并基于逗号前的每个值获取结果

问题描述

输入参数是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)

当报告布局不利于像您的上方光标那样进行迭代时,我已经做了几次。让我知道是否有帮助。我完全不确定整个脚本的目的是什么,但是希望它可以对如何实现此目标提供一些见识?