用oracle替换表的所有列中的值

时间:2016-12-27 05:09:55

标签: oracle plsql

我想替换匹配特定单词的表格的所有单元格。我写了这个问题:

UPDATE table_name 
SET column_name=REPLACE(column_name
                          ,'string_to_be_replaced'
                          , 'string_replaced') 

将替换 table_name 的所有列的值的过程不仅仅是上面代码中的一列?

这是我必须做的事情,并且再次更新一些表格。

由于

3 个答案:

答案 0 :(得分:2)

以下是一些测试数据:

SQL> select * from t23;

        ID NAME                 JOB
---------- -------------------- --------------------
        10 JACK                 JANITOR
        20 JAN                  TUTOR
        30 MOHAN                JAZZ DANCER
        40 JOAN                 MECHANIC

SQL> 

我想替换所有' JA'用' MO'。这意味着我需要更新NAME和JOB。显然我可以写一个UPDATE语句,但我也可以使用数据字典的魔力生成一个:

SQL> select column_name, data_type
  2  from user_tab_cols
  3  where table_name = 'T23';

COLUMN_NAME                    DATA_TYPE
------------------------------ ----------
ID                             NUMBER
NAME                           VARCHAR2
JOB                            VARCHAR2

SQL> 

这似乎是一次性的任务,我需要一个匿名的PL / SQL块而不是永久的过程。所以这是一个脚本,保存为gen_upd_stmt.sql

declare
    stmt varchar2(32767);
    target_string varchar2(20) := 'JA';
    replace_string varchar2(20) := 'MO';
begin
    stmt := 'update t23 set ';
    for lrec in ( select column_name
                          , row_number() over (order by column_id) as id
                 from user_tab_cols
                  where table_name = 'T23'
                  and data_type = 'VARCHAR2'
                 )
    loop
        if lrec.id > 1 then 
           stmt := stmt || ',';
        end if;
        stmt := stmt || lrec.column_name || '=replace('
                     || lrec.column_name || ', ''' || target_string
                     || ''',''' || replace_string 
                     || ''')';
    end loop;
    --  uncomment for debugging
    --  dbms_output.put_line(stmt);
    execute immediate stmt;
    dbms_output.put_line('rows updated = '|| to_char(sql%rowcount));
end;
/

请注意,生成动态SQL是一个粗糙的过程,因为语法错误是在运行时而不是编译时抛出的。逃避报价可能特别具有瘟疫性。显示生成的语句以使调试更容易,这是一个好主意。

另外,我将目标列限制为具有正确数据类型的列。这不是必须的,因为replace()将为我们处理类型转换(在大多数情况下)。但是使用大表来排除我们知道不匹配的列会更有效。

无论如何,让我们滚!

SQL> set serveroutput on
SQL> @gen_upd_stmt
rows updated = 4

PL/SQL procedure successfully completed.

SQL> 

正如预期的那样,所有四行都会更新,但并非所有行都会更改:

SQL> select * from t23;

        ID NAME                 JOB
---------- -------------------- --------------------
        10 MOCK                 MONITOR
        20 MON                  TUTOR
        30 MOHAN                MOZZ DANCER
        40 JOAN                 MECHANIC

SQL> 

为了完整性,生成的语句是:

update t23 set NAME=replace(NAME, 'JA','MO'),JOB=replace(JOB, 'JA','MO')

对于更大的表或更复杂的要求,我可能会使用chr(13)||chr(10)引入换行符,以使生成的代码更具可读性(用于调试)。

答案 1 :(得分:0)

你可以尝试这样的事情。请根据您的要求进行更新。

DECLARE

   L_statement VARCHAR2(4000) := 'UPDATE :table_name SET ';

   CURSOR c_get_cols IS
   SELECT column_name
     FROM dba_tab_cols
    WHERE table_name = :table_name;

   TYPE Cur_tab IS TABLE OF c_get_cols%ROWTYPE;
   L_tab Cur_tab;

BEGIN

   OPEN c_get_cols;
   FETCH C_get_cols INTO L_tab;
   CLOSE C_get_cols;

   FOR i IN 1..L_tab.COUNT
   LOOP
      L_statement := L_statement || L_tab(i).column_name || ' = REPLACE(column_name, :string_to_be_replaced, :string_replaced)';
      IF i != L_tab.COUNT
      THEN
         L_statement := L_statement || ',';
      END IF;
   END LOOP;

   EXECUTE IMMEDIATE L_statement;

END;
/

答案 2 :(得分:0)

我尝试使用cursor :(将owner和table_name替换为相应的值)

DECLARE 
 COL_NAME ALL_TAB_COLUMNS.COLUMN_NAME%TYPE;
  string_to_be_replaced VARCHAR2(20) ;
  string_replaced VARCHAR2 (20) ; 
  exc_invalid_id EXCEPTION;
   PRAGMA EXCEPTION_INIT(exc_invalid_id, -904);
  CURSOR c1 IS
  SELECT COLUMN_NAME FROM ALL_TAB_COLUMNS WHERE owner=<owner_name> AND TABLE_NAME=<table_name> ;
  BEGIN
  string_to_be_replaced :='';
   string_replaced :='';
  OPEN C1;
  LOOP 
  FETCH C1 INTO COL_NAME ;
  EXIT WHEN C1%NOTFOUND;
  EXECUTE immediate('UPDATE <owner_name>.<table_name> SET '||col_name||'=REPLACE('||col_name||','''||string_to_be_replaced||''','''||string_replaced||''')');    
  END LOOP;
  CLOSE C1;
  END;