以下是您的问题,有没有办法通过动态替换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);
答案 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)