动态修剪列值

Posted

技术标签:

【中文标题】动态修剪列值【英文标题】:Dynamically Trim Column Values 【发布时间】:2014-05-19 20:01:28 【问题描述】:

这里有一个问题要问大家,有没有办法通过动态替换cursor.column_name 语法中的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】:

不,你不能,而且你确实混淆了 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)

【讨论】:

感谢您的回复,我想您说了我需要听到的内容,我将在 ETL 过程中处理数据修剪。您关于动态构建 SELECT 的建议实际上是解决此问题的好方法,因此我感谢您付出的额外努力! 没问题@Roberto;设置一些东西来修剪所有东西很麻烦,但从长远来看,它会容易得多,因为你只需要做一次而不是每次......

以上是关于动态修剪列值的主要内容,如果未能解决你的问题,请参考以下文章

在 Oracle SQL 中生成动态列值

如何根据 azure databricks 中的列值将静态值传递给动态值

根据列值动态更改图标

根据列值动态获取列名

获取javascript中动态行的特定列值

使用动态查询更新表的“n”列值