如何运行从Oracle DB下的其他脚本生成的脚本?

时间:2011-04-11 21:01:38

标签: oracle sql-drop

有人知道如何将以下查询生成的所有行作为脚本运行吗?

select 'DROP TABLE '||table_name||' CASCADE CONSTRAINTS;' from user_tables;

我基本上要做的是删除我的数据库上的所有用户表和约束(这是oracle)。我得到的输出是正确的,但我想知道如何在没有复制/粘贴的情况下运行所有​​行。

此外,是否有更有效的方法来删除所有表(包括约束)?

4 个答案:

答案 0 :(得分:4)

begin
  for i in (select table_name from user_tables)
  loop
    execute immediate ('drop table ' || i.table_name || ' cascade constraints');
  end loop;
end;
/

Justin Cave提出了一个很好的观点 - 假设所有外键引用主键而不是唯一约束,以下内容将从依赖关系层次结构的最外层分支开始删除用户架构中的表。没有主键的表最后会丢弃。

begin
  for i in (select parent_table, max(tree_depth) as tree_depth
              from (select parent.table_name as parent_table,
                           child.constraint_name as foreign_key, 
                           child.table_name as child_table,
                           LEVEL AS TREE_DEPTH
                      from (select table_name, constraint_name
                              from USER_constraints
                             where constraint_type = 'P'
                           ) parent 
                           LEFT JOIN
                           (SELECT TABLE_NAME, CONSTRAINT_NAME, 
                                   r_constraint_name
                              FROM USER_CONSTRAINTS
                             WHERE CONSTRAINT_TYPE = 'R') child
                              on parent.constraint_name = 
                                    child.r_constraint_name
                           CONNECT BY NOCYCLE 
                             (PRIOR CHILD.TABLE_NAME = PARENT.TABLE_NAME)
                   UNION
                   select DT.table_name as parent_table,
                          NULL AS FOREIGN_KEY, NULL AS CHILD_TABLE,
                          0 AS TREE_DEPTH
                     FROM USER_TABLES DT
                    WHERE TABLE_NAME NOT IN
                          (SELECT TABLE_NAME
                             FROM USER_CONSTRAINTS
                            WHERE CONSTRAINT_TYPE = 'P')
                   )
             group by parent_table
             order by 2 desc
           )
  loop
    execute immediate ('drop table ' || i.parent_table || 
                       ' cascade constraints');
  end loop;
end;
/

答案 1 :(得分:3)

快速而肮脏的解决方案是做类似

的事情
FOR x IN (SELECT * FROM user_tables)
LOOP
  BEGIN
    EXECUTE IMMEDIATE 'DROP TABLE ' || x.table_name || 
                        ' CASCADE CONSTRAINTS';
  EXCEPTION
    WHEN others THEN
      dbms_output.put_line( 'Failed to drop ' || x.table_name ); 
  END;
END LOOP;

并多次运行,直到所有表都被删除。这将需要多次传递,因为在仍然存在具有引用父级的外键的子表时,您不能删除父表。

更清洁的选项是针对数据字典编写分层查询以获取子表,这些子项的父项,祖父母等,并使树行走以丢弃适当的对象。这应该避免错误,但需要更多的工作来编码。

答案 2 :(得分:1)

execute immediate - 传入生成的字符串

答案 3 :(得分:1)

删除表以使用truncate语句时通常会更有效。

您可以使用execute immediate命令

执行动态脚本