【问题标题】:replace values in all columns of a table with oracle用oracle替换表的所有列中的值
【发布时间】:2016-12-27 21:37:09
【问题描述】:

我想替换表格中与特定单词匹配的所有单元格。我写了这个查询:

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

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

这是我必须一遍又一遍地更新一些表格的事情。

谢谢

【问题讨论】:

  • 问题是什么:)?

标签: oracle plsql


【解决方案1】:

这是一些测试数据:

SQL> select * from t23;

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

SQL> 

我想用“MO”替换所有“JA”实例。这意味着我需要更新 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) 引入换行符,以使生成的代码更具可读性(用于调试)。

【讨论】:

    【解决方案2】:

    你可以试试这样的。其余根据您的要求更新它。

    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;
    /
    

    【讨论】:

      【解决方案3】:

      我使用游标尝试过:(将所有者和表名替换为各自的值)

      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;      
      

      【讨论】:

        猜你喜欢
        • 2022-12-21
        • 2022-07-03
        • 2022-10-14
        • 2016-09-12
        • 1970-01-01
        • 2021-06-19
        • 1970-01-01
        • 2015-07-22
        • 2021-08-31
        相关资源
        最近更新 更多