查找并替换,循环遍历oracle DB中的所有表

时间:2013-05-15 19:27:53

标签: database oracle loops replace

我正在尝试遍历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;

1 个答案:

答案 0 :(得分:3)

提醒

如果您实际上尝试替换架构中每个表中每个列的字符串值,请注意它将花费小时,至少。

除了免责声明之外,类似的脚本在许多情况下都很有用(可能更改列名,可能执行大量数据清理,或者从元数据表创建表)。

一般方法

基本上,您需要:

  1. 遍历目标架构中的每个表
  2. 对于每个表,循环遍历每个VARCHAR2
  3. 对于每列,生成UPDATE语句并执行它
  4. 更智能的解决方案只为每个表生成一个UPDATE语句。那么您的解决方案将是:

    1. 遍历目标架构中的每个表
    2. 对于每个表,生成UPDATE语句的第一部分,直到SET子句
    3. 对于每列,将SET子句的一部分附加到您的陈述
    4. 执行您的陈述
    5. 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;
      /