【问题标题】:Drop all objects on schema in Oracle在 Oracle 中删除模式上的所有对象
【发布时间】:2018-11-27 18:58:41
【问题描述】:

我正在尝试构建一个脚本来删除数据库上的所有对象,因此使用以下选择,构建一个要执行的过程,该过程将使数据库完全干净(无权删除数据库并再次创建它) .首先删除所有序列、索引等,然后删除表。

select 'drop '||object_type||' '|| object_name || ';' from user_objects where object_type in ('VIEW','PACKAGE','SEQUENCE', 'PROCEDURE', 'FUNCTION', 'INDEX')

考虑到这一点,我认为这样的事情可能会奏效:

BEGIN

    FOR i IN (select 'drop '||object_type||' '|| object_name || ';' from user_objects where object_type in ('VIEW','PACKAGE','SEQUENCE', 'PROCEDURE', 'FUNCTION', 'INDEX'))
    LOOP
        EXECUTE IMMEDIATE i;
    END LOOP;

END;
/

但我明白了:

错误报告 - ORA-06550:第 5 行,第 27 列:PLS-00382:表达式为 错误类型 ORA-06550:第 5 行,第 9 列:PL/SQL:语句被忽略 06550. 00000 - “第 %s 行,第 %s 列:\n%s” *原因:通常是 PL/SQL 编译错误。 *行动:

知道如何执行此操作吗?

【问题讨论】:

  • 为什么不简单地DROP USER ... CASCADE;
  • 你为什么喜欢先删除索引然后删除表?如果您删除该表,则该表的所有索引也将被删除。物化视图呢?
  • DROPCREATE 用户当然是优雅的,但需要额外的权限。
  • 跳过';'
  • @WernfriedDomscheit 用户没有权限执行删除用户(也不能删除自己)。你的意思是跳过';'在 select 语句中?

标签: oracle


【解决方案1】:

execute immediate 需要一个字符串(或 varchar2)参数。你给它一个光标行。给您选择的值一个别名并将其用作参数,并且不要在语句中包含分号,如下所示:

begin
  for i in (select 'drop ' || object_type || ' ' || object_name as stmt
              from user_objects
             where object_type in ('VIEW', 'PACKAGE', 'SEQUENCE', 'PROCEDURE', 'FUNCTION', 'INDEX')) loop
    execute immediate i.stmt;
  end loop;
end;
/

【讨论】:

  • +1 为您提供帮助。当对象类型不可用时,这将引发错误。请确保您只传递所需的对象类型,如 TABLE、SEQUENCE 等。当您删除表时,它也会删除相关索引。因此,除非您的索引很少与表无关,否则无需明确提及 INDEX。
  • 得到错误ORA-02449: unique/primary keys in table referenced by foreign keys
  • @Bishan 删除表的语句可以修改为:DROP TABLE <table_name> CASCADE CONSTRAINTS。 CASCADE CONSTRAINTS 选项还将删除引用正在删除的表的任何外键约束,从而避免该错误。
  • @GriffeyDog 是的,通过CASCADE CONSTRAINTS 实现。感谢您的更新。
【解决方案2】:

出于测试目的,我使用 Scott 的模式。一旦污染太严重,我会丢弃除 Scott 的默认表之外的所有内容。这是我的脚本;看看它对你的情况是否有帮助。

请注意,您必须多次运行它,因为它不关心外键约束,这些约束不会让您在主表的详细信息存在时删除它们,但这并没有让我感到困扰。

declare
  l_str varchar2(200);
begin
  for cur_r in (select object_name, object_type From user_objects 
                where object_name not in ('EMP', 'DEPT', 'BONUS', 'SALGRADE')
               )
  loop
    begin
      l_str := 'drop ' || cur_r.object_type || ' '|| cur_r.object_name;
      dbms_output.put_Line(l_str);
      execute immediate l_str;
    exception
      when others then null;
    end;
  end loop;
end;
/

【讨论】:

  • 实际问题是“删除所有对象”恕我直言应该包括队列等。所以仍然没有最终回答。我的猜测是 Oracle RDBMS 需要像其他一些数据库一样正确支持这一点。因为它没有,所以没有完全可用的解决方案,您必须删除并重新创建用户。如果您没有相应的许可,最终会导致大量手动摆弄:(
  • 当然,@Jörg。我不知道有谁真正从用于生产目的的模式中删除所有对象。 也许出于教育目的(即每个新学生都有自己的干净架构),但我宁愿删除旧用户并导入一个新用户,清洁一个。我发布的代码适用于我的 Scott 用户,用于回答我在各种 Oracle 论坛/站点上找到的问题。我懒得删除/导入,所以我运行该代码,我对它的作用感到满意。
  • 恕我直言,没有人在生产中这样做,但在接近开发的测试环境中,这对于 liquibase 或 flyway 来说是很正常的。顺便说一句:Oracle 的另一种解决方法是将 SQL 幂等创建为一种“CREATE IF NOT EXISTS”(伪语法,使用网络搜索来查找实际情况的真实 SQL)。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2015-07-07
  • 2020-05-03
  • 1970-01-01
  • 2018-11-25
  • 2018-12-27
  • 2019-11-28
相关资源
最近更新 更多