我想替换匹配特定单词的表格的所有单元格。我写了这个问题:
UPDATE table_name
SET column_name=REPLACE(column_name
,'string_to_be_replaced'
, 'string_replaced')
将替换 table_name 的所有列的值的过程不仅仅是上面代码中的一列?
这是我必须做的事情,并且再次更新一些表格。
由于
答案 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;