Oracle,drop table如果存在且为空

时间:2013-09-23 23:13:23

标签: oracle plsql ddl

我需要删除Oracle表,只有它存在且2)不是空的 我编写了这段代码但是如果表不存在则代码不起作用:

DECLARE
  rec_cnt1 NUMBER :=0;
  rec_cnt2 NUMBER :=0;
BEGIN
  SELECT COUNT(*) INTO rec_cnt1 FROM ALL_TABLES  WHERE TABLE_NAME  = 'MyTable';
  SELECT num_rows INTO rec_cnt2 FROM USER_TABLES WHERE TABLE_NAME  = 'MyTable';
  IF rec_cnt1 = 1 THEN
  BEGIN
    IF rec_cnt2 < 1 THEN
      EXECUTE IMMEDIATE 'DROP TABLE MyTable cascade constraints';
    END IF;
  END;
  END IF;
END;
/

我做错了什么?请帮忙。

非常感谢提前

4 个答案:

答案 0 :(得分:4)

如果你想删除一个表,如果它存在并且为空(如问题的标题所示),你可以按如下方式执行:

create or replace procedure DropTableIfEmpty(p_tab_name varchar2)
is
  l_tab_not_exists exception;
  pragma exception_init(l_tab_not_exists, -942);
  l_is_empty   number;
  l_query      varchar2(1000);
  l_table_name varchar2(32);
begin
  l_table_name := dbms_assert.simple_sql_name(p_tab_name);
  l_query := 'select count(*)
                from ' || l_table_name ||          
             ' where rownum = 1';
  execute immediate l_query
     into l_is_empty;

  if l_is_empty = 0
  then
    execute immediate 'drop table ' || l_table_name;
    dbms_output.put_line('Table "'|| p_tab_name ||'" has been dropped');
  else
    dbms_output.put_line('Table "'|| p_tab_name ||'" exists and is not empty');
  end if;

exception
  when l_tab_not_exists
  then dbms_output.put_line('Table "'|| p_tab_name ||'" does not exist');
end;

当您尝试删除表或查询不存在的表时,Oracle将引发ORA-00942异常并执行pl / sql块暂停。我们使用pragma exception_init语句将ORA-00942异常与我们本地定义的异常l_tab_not_exists相关联,以便正确处理它。

测试用例:

SQL> exec droptableifempty('tb_test');  -- tb_test table does not exists

 Table "tb_test" does not exist

SQL> create table tb_test(
  2     col number
  3   );

table TB_TEST created.

SQL> exec droptableifempty('tb_test'); 

 Table "tb_test" has been dropped

作为旁注。在查询num_rows的{​​{1}}列以确定表的行数之前,您需要通过执行[dba][all][user]_tables来收集表统计信息,否则您将无法获得实际的行数。 / p>

答案 1 :(得分:0)

在PL / SQL中它是正常的&#39;赶上例外。

如果是正确的例外,请继续使用代码的下一部分。

DECLARE
  rec_cnt1 NUMBER :=0;
  rec_cnt2 NUMBER :=0;
BEGIN
  SELECT COUNT(*) INTO rec_cnt1 FROM ALL_TABLES  WHERE TABLE_NAME  = 'MyTable';
  SELECT num_rows INTO rec_cnt2 FROM USER_TABLES WHERE TABLE_NAME  = 'MyTable';
  IF rec_cnt1 = 1 THEN
  BEGIN
    IF rec_cnt2 < 1 THEN
      EXECUTE IMMEDIATE 'DROP TABLE MyTable cascade constraints';
    END IF;
  END;
  END IF;
EXCEPTION
  DBMS_OUTPUT.PUT_LINE('OH DEAR AN EXCEPTION WAS THROWN DUE TO' || SQLERRM);
  DBMS_OUTPUT.PUT_LINE('THE ORACLE CODE IS ' || SQLCODE);
  -- if it is the oracle code for no such table, or no data selected
  -- everything is fine.

END;

答案 2 :(得分:-1)

当然,如果表不存在,它将无法工作。您的第二个选择将获得“未找到数据”异常,并且您没有进行任何异常处理。至少你应该在第一个IF块内移动第二个选择。最好添加异常处理。

答案 3 :(得分:-2)

这是解决此问题的简便方法:

BEGIN 
     EXECUTE IMMEDIATE 'DROP TABLE [sssss]'; 
     EXCEPTION WHEN OTHERS THEN NULL; 
END;