35

作为我们构建过程和不断发展的数据库的一部分,我正在尝试创建一个脚本,它将删除用户的所有表和序列。我不想重新创建用户,因为这将需要比允许更多的权限。

我的脚本创建一个过程来删除表/序列,执行该过程,然后删除该过程。我正在从 sqlplus 执行文件:

删除.sql:


create or replace procedure drop_all_cdi_tables
is
cur integer;
begin
cur:= dbms_sql.OPEN_CURSOR();
for t in (select table_name from user_tables) loop
execute immediate 'drop table ' ||t.table_name|| ' cascade constraints';
end loop;
dbms_sql.close_cursor(cur);

cur:= dbms_sql.OPEN_CURSOR();
for t in (select sequence_name from user_sequences) loop
execute immediate 'drop sequence ' ||t.sequence_name;
end loop;
dbms_sql.close_cursor(cur);
end;
/
execute drop_all_cdi_tables;
/
drop procedure drop_all_cdi_tables;
/

不幸的是,放弃该过程会导致问题。似乎会导致竞争条件,并且该过程在执行之前被丢弃。
例如:

SQL*Plus:发布 11.1.0.7.0 - 2010 年 3 月 30 日星期二 18:45:42 生产

 版权所有 (c) 1982、2008,甲骨文。版权所有。


 连接到:
 Oracle Database 11g 企业版 11.1.0.7.0 - 64 位生产
 具有分区、OLAP、数据挖掘和实际应用程序测试选项


 程序已创建。


 PL/SQL 过程成功完成。


 程序已创建。


 程序下降。

 删除过程 drop_all_user_tables
 *
 第 1 行的错误:
 ORA-04043: 对象 DROP_ALL_USER_TABLES 不存在


 SQL> 与 Oracle Database 11g 企业版 11.1.0.7.0 - 64 版断开连接
 具有分区、OLAP、数据挖掘和实际应用程序测试选项

关于如何使它工作的任何想法?

4

6 回答 6

83

如果您不打算保留存储过程,我会使用匿名 PLSQL 块

BEGIN

  --Bye Sequences!
  FOR i IN (SELECT us.sequence_name
              FROM USER_SEQUENCES us) LOOP
    EXECUTE IMMEDIATE 'drop sequence '|| i.sequence_name ||'';
  END LOOP;

  --Bye Tables!
  FOR i IN (SELECT ut.table_name
              FROM USER_TABLES ut) LOOP
    EXECUTE IMMEDIATE 'drop table '|| i.table_name ||' CASCADE CONSTRAINTS ';
  END LOOP;

END;
于 2010-03-31T01:21:39.300 回答
6

对于 SQL 语句,末尾的分号将执行该语句。/ 将执行前面的语句。因此,您结束行

drop procedure drop_all_cdi_tables;
/

将删除该过程,然后尝试再次删除它。

如果您查看您的输出,您将看到“PROCEDURE CREATED”,然后执行,然后再次执行“PROCEDURE CREATED”,因为它重新执行最后一条语句(EXECUTE 是 SQL*Plus 命令,不是语句,因此没有缓冲) 然后是“PROCEDURE DROPPED”,然后它会尝试(但失败)第二次删除它。

PS。我同意 Dougman 对奇怪的 DBMS_SQL 调用的看法。

于 2010-03-31T01:36:36.420 回答
4

只需运行这两个语句,然后运行所有结果:

select 'drop table ' || table_name || ';' from user_tables;
select 'drop sequence ' || sequence_name || ';' from user_sequences;
于 2018-02-10T09:25:22.377 回答
2

看起来您的示例错误消息出现错误,drop_all_user_tables但您给出的示例是 for drop_all_cdi_tablesdrop_all_user_tables代码看起来不一样吗?

您也有调用dbms_sql但似乎没有使用它进行任何解析。

于 2010-03-31T01:23:45.603 回答
1

除了 OMG Ponies 提供的解决方案之外,如果您有带有空格的序列,则需要稍微增强 PLSQL:

BEGIN
  FOR i IN (SELECT sequence_name FROM user_sequences)
    Loop
      EXECUTE IMMEDIATE('"DROP SEQUENCE ' || user || '"."' || i.sequence_name || '"');
    End Loop;
End;
/
于 2015-06-01T08:47:17.860 回答
0

由于某种原因,OMG Ponies 解决方案在 PLSQL 上给出了错误“SQL 命令未正确结束”。如果其他人遇到同样的问题,这就是我如何能够删除当前模式中的所有表。

DECLARE
  table_name VARCHAR2(30);
  CURSOR usertables IS SELECT * FROM user_tables WHERE table_name NOT LIKE 'BIN$%';
BEGIN
  FOR i IN usertables
  LOOP
  EXECUTE IMMEDIATE 'drop table ' || i.table_name || ' cascade constraints';
  END LOOP;
END;
/

学分:Snippler

于 2016-10-24T18:41:21.593 回答