删除Oracle中的多个尾随空格和更新列

时间:2018-02-22 20:19:53

标签: oracle

我有一个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  |   |   |
------------------------------------

2 个答案:

答案 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;