将regexp_replace连接到listagg:结果太长(SQL错误:ORA-01489)

时间:2018-10-10 14:22:17

标签: oracle plsql dynamic-sql regexp-replace listagg

我为一个正在创建应该匹配的表集之间进行协调的包创建了pl/sql procedure

我正在使用listagg将循环中当前表名的列名连接成一个字符串,该字符串用于动态SQL语句,该语句比较两个表(每个表名都有34个循环)。

该过程按预期工作,但结果从负号意外返回。经过研究,我确定某些字段包含在平面文件中接收到的十六进制(00)字符,该字符仅将数据填充在侦察器一侧的数据上。为了解决特殊字符,我在列名select中添加了一个与listagg串联的regexp_replace,以便输出完整的listagg结果,每个列名都包装在regexp_replace中。

有效。但是,有些表有一百多列,并且listagg失败,结果超过4000个字符。

是否有更好的方法来解决这整个问题?

代码如下:

将列名称收集到以逗号分隔的列表中(逗号字符连接到字符串本身中,用作动态SQL中的分隔符,请在下面选择)

execute immediate
'SELECT ' || q'{listagg('regexp_replace(' || column_name || ', ''[^A-Z0-9 ]'', '''')',  '||'', '' || ')}' || ' within group (order by rownum) "COLUMN_NAME"
FROM user_tab_cols
where table_name =''' || csrpubtable.table_name || ''''

into v_column_names;

这两个动态SQL语句在两个方向上执行协调。这些与错误没有直接关系,但绝对与我有更好的整体方法来完成任务的问题有关。

--Insert data to RECON_PUB_TABLES where record exists in FILE but not PROD
execute immediate
'INSERT INTO RECON_PUB_TABLES
SELECT ''' || csrpubtable.table_name || ''', ''FILE'' , ' || v_column_names || ', trunc(sysdate) from ' || csrpubtable.table_name || '
minus
SELECT ''' || csrpubtable.table_name || ''', ''FILE'' , ' || v_column_names || ', trunc(sysdate) from ' || csrpubtable.table_name || '@pub_recon2prod where trunc(' || v_lastupdate_column || ') <= trunc(to_date(''' || v_compare_date || ''', ''dd-MON-yy''))';

--Insert data to RECON_PUB_TABLES where record exists in PROD but not FILE
execute immediate
'INSERT INTO RECON_PUB_TABLES
SELECT ''' || csrpubtable.table_name || ''', ''PROD'' , ' || v_column_names || ', trunc(sysdate) from ' || csrpubtable.table_name || '@pub_recon2prod where trunc(' || v_lastupdate_column || ') <= trunc(to_date(''' || v_compare_date || ''', ''dd-MON-yy''))
minus
SELECT ''' || csrpubtable.table_name || ''', ''PROD'' , ' || v_column_names || ', trunc(sysdate) from ' || csrpubtable.table_name ;

1 个答案:

答案 0 :(得分:1)

varsql2在plsql中限制为32k 如果32就足够了,您可以尝试这样的事情

create or replace procedure conc_col_names(tableName IN varchar2)  as 
  collist varchar2(32767); 
begin
  for xx in (select * from user_tab_columns where table_name = tableName order by column_name asc) loop
    if ( length(collist) > 0) then 
      collist := collist||','; 
    end if; 
    collist := collist||'regexp_replace('||xx.column_name||',''[^A-Z0-9 ]'')';
  end loop;

  /* add the rest code for comparing rows in the two table here  */

end; 
/