删除Oracle中的所有用户表/序列
作为我们构建过程和不断发展的数据库的一部分,我正在尝试创建一个脚本来删除用户的所有表和序列。我不想重新创建用户,因为这将需要比允许的更多的权限。
我的脚本创建一个过程来删除表/序列,执行该过程,然后删除该过程。我正在从 sqlplus 执行该文件:
drop.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: Release 11.1.0.7.0 - Production on Tue Mar 30 18:45:42 2010 Copyright (c) 1982, 2008, Oracle. All rights reserved. Connected to: Oracle Database 11g Enterprise Edition Release 11.1.0.7.0 - 64bit Production With the Partitioning, OLAP, Data Mining and Real Application Testing options Procedure created. PL/SQL procedure successfully completed. Procedure created. Procedure dropped. drop procedure drop_all_user_tables * ERROR at line 1: ORA-04043: object DROP_ALL_USER_TABLES does not exist SQL> Disconnected from Oracle Database 11g Enterprise Edition Release 11.1.0.7.0 - 64 With the Partitioning, OLAP, Data Mining and Real Application Testing options
关于如何让它发挥作用有什么想法吗?
As part of our build process and evolving database, I'm trying to create a script which will remove all of the tables and sequences for a user. I don't want to do recreate the user as this will require more permissions than allowed.
My script creates a procedure to drop the tables/sequences, executes the procedure, and then drops the procedure. I'm executing the file from sqlplus:
drop.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;
/
Unfortunately, dropping the procedure causes a problem. There seems to cause a race condition and the procedure is dropped before it executes.
E.g.:
SQL*Plus: Release 11.1.0.7.0 - Production on Tue Mar 30 18:45:42 2010 Copyright (c) 1982, 2008, Oracle. All rights reserved. Connected to: Oracle Database 11g Enterprise Edition Release 11.1.0.7.0 - 64bit Production With the Partitioning, OLAP, Data Mining and Real Application Testing options Procedure created. PL/SQL procedure successfully completed. Procedure created. Procedure dropped. drop procedure drop_all_user_tables * ERROR at line 1: ORA-04043: object DROP_ALL_USER_TABLES does not exist SQL> Disconnected from Oracle Database 11g Enterprise Edition Release 11.1.0.7.0 - 64 With the Partitioning, OLAP, Data Mining and Real Application Testing options
Any ideas on how to get this working?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(6)
看起来您的示例错误消息在
drop_all_user_tables
上出现错误,但您给出的示例是针对drop_all_cdi_tables
的。drop_all_user_tables
代码看起来有什么不同吗?此外,您还调用了 dbms_sql ,但似乎没有使用它进行任何解析。
It looks like your example error message is getting an error on
drop_all_user_tables
but the example you gave is fordrop_all_cdi_tables
. Does thedrop_all_user_tables
code look different?Also you have calls to
dbms_sql
but don't seem to be using it do any parsing.除了 OMG Ponies 提出的解决方案之外,如果序列中有空格,则需要稍微增强 PLSQL:
In addition to the solution presented by OMG Ponies, if you have sequences with blank spaces, you need to enhance the PLSQL a bit:
由于某种原因,OMG Ponies 解决方案在 PLSQL 上给出了错误“SQL 命令未正确结束”。如果其他人遇到同样的问题,以下是我如何删除当前模式中的所有表。
学分:Snippler
For some reason OMG Ponies solution gave an error "SQL command not properly ended" on PLSQL. In case someone else comes across the same problem, here is how I was able to delete all the tables in the current schema.
Credits: Snippler
如果您不打算保留存储过程,我会使用 匿名 PLSQL块:
If you're not intending on keeping the stored procedure, I'd use an anonymous PLSQL block:
对于 SQL 语句,末尾的分号将执行该语句。
/ 将执行前面的语句。
因此,您结束
will drop 该过程的行,然后尝试再次删除它。
如果查看输出,您将看到“PROCEDURE CREATED”,然后执行,然后再次执行“PROCEDURE CREATED”,因为它重新执行最后一条语句(EXECUTE 是 SQL*Plus 命令,不是语句,因此不会缓冲)然后“PROCEDURE DROPPED”,然后它第二次尝试(但失败)删除它。
附言。我同意 Dougman 关于奇怪的 DBMS_SQL 调用的观点。
For an SQL statement, the semi-colon at the end will execute the statement.
The / will execute the previous statement.
As such, you end lines of
will drop the procedure, then try to drop it again.
If you look at your output, you'll see 'PROCEDURE CREATED', then executed, then 'PROCEDURE CREATED' again as it re-executes the last statement (EXECUTE is a SQL*Plus command, not a statement so isn't buffered) then "PROCEDURE DROPPED" and then it tries (and fails) to drop it the second time.
PS. I agree with Dougman on the odd DBMS_SQL calls.
只需运行这两条语句,然后运行所有结果:
Just run these two statements and then run all the results: