我正在尝试遍历oracle DB中的每个表,并查找并替换字符串值。对于整个数据库中的所有条目,我想查找字符串值的所有实例,将其替换为另一个字符串值。我很接近,但由于某种原因,我的代码没有正确响应。
DECLARE
CURSER all_tables IS
SELECT table_name FROM all_tables;
v_count NUMBER;
BEGIN
FOR host IN all_tables LOOP
SELECT REPLACE('jack','j','b') "Changes"
FROM host
END LOOP;
END;
答案 0 :(得分:3)
提醒
如果您实际上尝试替换架构中每个表中每个列的字符串值,请注意它将花费小时,至少。
除了免责声明之外,类似的脚本在许多情况下都很有用(可能更改列名,可能执行大量数据清理,或者从元数据表创建表)。
一般方法
基本上,您需要:
VARCHAR2
列UPDATE
语句并执行它更智能的解决方案只为每个表生成一个UPDATE
语句。那么您的解决方案将是:
UPDATE
语句的第一部分,直到SET
子句SET
子句的一部分附加到您的陈述Oracle 10g / 11g的示例代码,使用众所周知的HR模式:
每列一个UPDATE语句
DECLARE
schemaName VARCHAR2(30) := 'HR';
stmt VARCHAR2(32767); -- on 11g, use CLOB
BEGIN
FOR tr IN (
SELECT t.OWNER, t.TABLE_NAME
FROM ALL_TABLES t
WHERE t.OWNER = schemaName
ORDER BY 1, 2
)
LOOP
FOR cr IN (
SELECT c.COLUMN_NAME
FROM ALL_TAB_COLUMNS c
WHERE c.OWNER = tr.OWNER AND c.TABLE_NAME = tr.TABLE_NAME
AND c.DATA_TYPE = 'VARCHAR2'
ORDER BY 1
)
LOOP
stmt := 'UPDATE '||tr.OWNER||'.'||tr.TABLE_NAME
||' SET '||cr.COLUMN_NAME||' = REPLACE('||cr.COLUMN_NAME||', ''j'', ''b'')';
DBMS_OUTPUT.PUT_LINE(stmt||';'); -- useful for debugging
EXECUTE IMMEDIATE stmt;
END LOOP;
END LOOP;
END;
/
每个表一个UPDATE语句
您可以尝试更聪明,并且只对表中的所有列使用一个UPDATE
语句。小心不要溢出stmt
变量。
DECLARE
schemaName VARCHAR2(30) := 'HR';
stmt VARCHAR2(32767); -- on 11g, use CLOB
do_update BOOLEAN;
BEGIN
FOR tr IN (
SELECT t.OWNER, t.TABLE_NAME
FROM ALL_TABLES t
WHERE t.OWNER = schemaName
ORDER BY 1, 2
)
LOOP
do_update := FALSE;
stmt := 'UPDATE '||tr.OWNER||'.'||tr.TABLE_NAME||' SET ';
FOR cr IN (
SELECT c.COLUMN_NAME
FROM ALL_TAB_COLUMNS c
WHERE c.OWNER = tr.OWNER AND c.TABLE_NAME = tr.TABLE_NAME
AND c.DATA_TYPE = 'VARCHAR2'
ORDER BY 1
)
LOOP
do_update := TRUE;
stmt := stmt||cr.COLUMN_NAME||' = REPLACE('||cr.COLUMN_NAME||', ''j'', ''b''), ';
END LOOP;
IF do_update THEN
stmt := SUBSTR(stmt, 1, LENGTH(stmt) - 2); -- remove trailing ', '
DBMS_OUTPUT.PUT_LINE(stmt||';'); -- useful for debugging
EXECUTE IMMEDIATE stmt;
END IF;
END LOOP;
END;
/