2

仅当 Oracle 表 1) 存在且 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

4 回答 4

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列之前[dba][all][user]_tables,为了确定一个表的行数,你需要通过执行来收集表的统计信息dbms_stats.gather_table_stats(user, '<<table_name>>');,否则你不会得到实际的行数。

于 2013-09-23T23:59:17.203 回答
0

在 PL/SQL 中,捕获异常是“正常的”。

如果它是正确的异常,则继续执行代码的下一部分。

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;
于 2013-09-24T00:06:48.917 回答
-1

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

于 2013-09-23T23:45:49.957 回答
-2

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

BEGIN 
     EXECUTE IMMEDIATE 'DROP TABLE [sssss]'; 
     EXCEPTION WHEN OTHERS THEN NULL; 
END;
于 2016-10-29T16:29:53.307 回答