动态修剪列值

时间:2014-05-19 20:01:29

标签: sql database oracle plsql oracle10g

以下是您的问题,有没有办法通过动态替换column_name语法中的cursor.column_name来使PL / SQL代码在下面工作?我知道我混淆了pl / sql引擎,但我不完全确定如何解决这个问题...

目前我收到以下错误,但我认为实际问题是pl / sql引擎不知道如何解释TRIM (e_rec.v_temp_column_name)

  

" [错误] PLS-00302(133:26):PLS-00302:组件   ' V_TEMP_COLUMN_NAME'必须声明"

参数: x_person_rec IN OUT xxsome_table%ROWTYPE

v_temp_column_name   dba_tab_columns.column_name%TYPE;
...
BEGIN
      FOR e_rec IN (SELECT * FROM xxsome_table WHERE ..)
      LOOP
         --LOG (3, 'Loading/Sanitizing Header Record');

         FOR col IN (SELECT column_name
                       FROM dba_tab_columns
                      WHERE table_name = UPPER ('xxsome_table'))
         LOOP
            --LOG (3, 'Sanitizing Column Name: ' || col.column_name);
            v_temp_column_name := col.column_name;
            x_person_rec.v_temp_column_name := TRIM (e_rec.v_temp_column_name);
         END LOOP;
      END LOOP; 

...

我尝试过这样做(会导致不同的错误):x_person_rec.col.column_name := TRIM (e_rec.col.column_name);

1 个答案:

答案 0 :(得分:2)

不,你不能和你确实混淆了PL / SQL引擎。问题是v_temp_column_name是一个字符,因此TRIM (e_rec.v_temp_column_name)被评估为TRIM (e_rec.'v_temp_column_name'),这没有任何意义。

如果尾随空格是个问题,最好的办法是确保当前应用程序/ ETL进程修剪所有放入数据库的数据。如果您不能这样做,那么使用触发器来确保它在数据库中发生。如果它是真正的坏问题,你甚至可以强制执行检查约束来阻止它发生。

现在,为了回答你的问题,这里没有必要动态地做任何事情。您的光标可能是隐式的,但它不是动态生成的。你知道表中的每一列都不那么懒,并把它们全部输出。

FOR e_rec IN (SELECT trim(col1) as col1
                   , trim(col2) as col2
                FROM xxsome_table WHERE ...

如果你无法修复你的数据(或者它没有被破坏!)那么这很容易就是最简单的方法。

要真正回答您的问题,您可以使用您在此处使用的相同技术动态构建SELECT语句...

declare
   l_cols varchar2(4000);
   l_curs sys_refcursor;
begin

   select wm_concat('trim(' || column_name || ')')
     into l_cols
     from user_tab_columns
    where table_name = 'XXSOME_TABLE'
          ;

    open l_curs for
     ' select ' || l_cols || ' from xxsome_table where ...';

    loop
      ...
    end loop;

end;
/

当你使用10g时,你不能使用优秀的LISTAGG(),但有plenty of other string aggregation techniques。请注意if the resulting string is greater than 4,000 bytes,您必须循环而不是在单个SQL语句中生成列列表。

P.S。,如果这些列是CHAR(n),那么每次选择时都必须修剪它们。可能值得将它们更改为VARCHAR2(n)