我有一个M * N行和列的oracle表,它有多个尾随空格。
我正在使用以下两个语句来查找尾随空格并更新值。我正在寻找一个可以在表上工作的脚本,不知道表有多少列,这些列的名称,以及哪些是数据类型varchar等。
Select * From Table Where Column_Name<> TRIM(Column_Name);
UPDATE Table
set Column_Name= trim(Column_Name)
where Condition=;
commit;
是否有一个脚本我可以一次更新整个表有多个尾随空格?
M*N |Columns| | |
------------------------------------
Rows |Trail | | |
------------------------------------
|Trail | | |
------------------------------------
| | | |
------------------------------------
| | |Trail |
------------------------------------
| |Trail | |
------------------------------------
| | | |
------------------------------------
| | | |
------------------------------------
|Trail | | |
------------------------------------
答案 0 :(得分:1)
这是你的问题的黑客攻击。如果您不止一次使用该程序,则必须处理该程序。特别是我不处理错误,我只查看VARCHAR2列。
SETUP:
create table tbl ( id number, name varchar2(10), notes varchar2(30) );
insert into tbl values ( 1, 'Joe ', 'No notes' );
insert into tbl values ( 2, 'Ann' , 'Spaces ' );
insert into tbl values ( 3, 'Ben' , null );
commit;
select id, '*|'||name||'|*' as name, '*|'||notes||'|*' as notes
from tbl
;
ID NAME NOTES
-- -------------- ----------------------------------
1 *|Joe |* *|No notes|*
2 *|Ann|* *|Spaces |*
3 *|Ben|* *||*
注意第一行中的名称和第二行中的注释 - 它们具有尾随空格。我添加了前导*|
并尾随|*
以显示尾随空格的位置。
更新此表的正确方法是
update tbl
set name = rtrim(name), notes = rtrim(notes)
where name like '% ' or notes like '% '
;
- 注意WHERE子句,以确保我们不更新没有任何带尾随空格的值的行。 (将行更新为自身似乎无害,但它会增加大量开销,并且会生成所有撤消和重做。)
那么,这是PL / SQL代码动态生成这个UPDATE
语句:
create or replace procedure trim_trailing_spaces (
tbl_name in varchar2,
own in varchar2 default null
)
as
sql_text varchar2(4000)
:= 'update ' || nvl(own, user) || '.' || tbl_name;
set_text varchar2(1000)
:= chr(10) || ' set ';
where_text varchar2(1000)
:= chr(10) || ' where ';
begin
for r in ( select column_name as col
from all_tab_columns
where owner = nvl(upper(own), user)
and table_name = upper(tbl_name)
and data_type = 'VARCHAR2'
)
loop
set_text := set_text || r.col || ' = rtrim( ' || r.col || '), ';
where_text := where_text || r.col || ' like ''% '' or ';
end loop;
sql_text := sql_text || rtrim(set_text, ', ') || rtrim(where_text, 'or ');
execute immediate sql_text;
commit;
end trim_trailing_spaces;
/
编译它然后执行它。我传入了表名'tbl'
(我们之前创建的表),并且我没有给出可选的第二个参数(对于不同于我自己的模式名称),因此更新的表将是我的模式中的表。然后我执行上面的SELECT
语句来查看更改。
exec trim_trailing_spaces('tbl')
select id, '*|'||name||'|*' as name, '*|'||notes||'|*' as notes
from tbl
;
ID NAME NOTES
-- -------------- ----------------------------------
1 *|Joe|* *|No notes|*
2 *|Ann|* *|Spaces|*
3 *|Ben|* *||*
所以,它似乎有效。
答案 1 :(得分:0)
以下是我能想到的最简单的。 如果对生成的输出感到满意,请将dbms_output.put_line替换为execute immediate。如果在您的情况下有意义,请取消注释提交。
BEGIN
FOR col_i IN (SELECT OWNER, table_name, column_name FROM all_tab_columns WHERE OWNER = 'XXX' AND table_name = 'YYY' AND (data_type LIKE '%CHAR%' OR data_type LIKE '%CLOB') )
LOOP
dbms_output.put_line('UPDATE ' || col_i.OWNER || '.' || col_i.table_name ||' set ' || col_i.column_name || ' = LTRIM(' || col_i.column_name || ') WHERE ' || col_i.column_name || ' LIKE '' %''');
-- commit;
END LOOP;
end;