Oracle: If Table Exists

后端 未结 15 1306
无人共我
无人共我 2020-11-22 13:32

I\'m writing some migration scripts for an Oracle database, and was hoping Oracle had something similar to MySQL\'s IF EXISTS construct.

Specifically, w

相关标签:
15条回答
  • 2020-11-22 14:02

    just wanted to post a full code that will create a table and drop it if it already exists using Jeffrey's code (kudos to him, not me!).

    BEGIN
        BEGIN
             EXECUTE IMMEDIATE 'DROP TABLE tablename';
        EXCEPTION
             WHEN OTHERS THEN
                    IF SQLCODE != -942 THEN
                         RAISE;
                    END IF;
        END;
    
        EXECUTE IMMEDIATE 'CREATE TABLE tablename AS SELECT * FROM sourcetable WHERE 1=0';
    
    END;
    
    0 讨论(0)
  • 2020-11-22 14:02

    I prefer following economic solution

    BEGIN
        FOR i IN (SELECT NULL FROM USER_OBJECTS WHERE OBJECT_TYPE = 'TABLE' AND OBJECT_NAME = 'TABLE_NAME') LOOP
                EXECUTE IMMEDIATE 'DROP TABLE TABLE_NAME';
        END LOOP;
    END;
    
    0 讨论(0)
  • 2020-11-22 14:05

    With SQL*PLUS you can also use the WHENEVER SQLERROR command:

    WHENEVER SQLERROR CONTINUE NONE
    DROP TABLE TABLE_NAME;
    
    WHENEVER SQLERROR EXIT SQL.SQLCODE
    DROP TABLE TABLE_NAME;
    

    With CONTINUE NONE an error is reported, but the script will continue. With EXIT SQL.SQLCODE the script will be terminated in the case of an error.

    see also: WHENEVER SQLERROR Docs

    0 讨论(0)
  • 2020-11-22 14:08

    Sadly no, there is no such thing as drop if exists, or CREATE IF NOT EXIST

    You could write a plsql script to include the logic there.

    http://download.oracle.com/docs/cd/B12037_01/server.101/b10759/statements_9003.htm

    I'm not much into Oracle Syntax, but i think @Erich's script would be something like this.

    declare 
    cant integer
    begin
    select into cant count(*) from dba_tables where table_name='Table_name';
    if count>0 then
    BEGIN
        DROP TABLE tableName;
    END IF;
    END;
    
    0 讨论(0)
  • 2020-11-22 14:10

    The best and most efficient way is to catch the "table not found" exception: this avoids the overhead of checking if the table exists twice; and doesn't suffer from the problem that if the DROP fails for some other reason (that might be important) the exception is still raised to the caller:

    BEGIN
       EXECUTE IMMEDIATE 'DROP TABLE ' || table_name;
    EXCEPTION
       WHEN OTHERS THEN
          IF SQLCODE != -942 THEN
             RAISE;
          END IF;
    END;
    

    ADDENDUM For reference, here are the equivalent blocks for other object types:

    Sequence

    BEGIN
      EXECUTE IMMEDIATE 'DROP SEQUENCE ' || sequence_name;
    EXCEPTION
      WHEN OTHERS THEN
        IF SQLCODE != -2289 THEN
          RAISE;
        END IF;
    END;
    

    View

    BEGIN
      EXECUTE IMMEDIATE 'DROP VIEW ' || view_name;
    EXCEPTION
      WHEN OTHERS THEN
        IF SQLCODE != -942 THEN
          RAISE;
        END IF;
    END;
    

    Trigger

    BEGIN
      EXECUTE IMMEDIATE 'DROP TRIGGER ' || trigger_name;
    EXCEPTION
      WHEN OTHERS THEN
        IF SQLCODE != -4080 THEN
          RAISE;
        END IF;
    END;
    

    Index

    BEGIN
      EXECUTE IMMEDIATE 'DROP INDEX ' || index_name;
    EXCEPTION
      WHEN OTHERS THEN
        IF SQLCODE != -1418 THEN
          RAISE;
        END IF;
    END;
    

    Column

    BEGIN
      EXECUTE IMMEDIATE 'ALTER TABLE ' || table_name
                    || ' DROP COLUMN ' || column_name;
    EXCEPTION
      WHEN OTHERS THEN
        IF SQLCODE != -904 AND SQLCODE != -942 THEN
          RAISE;
        END IF;
    END;
    

    Database Link

    BEGIN
      EXECUTE IMMEDIATE 'DROP DATABASE LINK ' || dblink_name;
    EXCEPTION
      WHEN OTHERS THEN
        IF SQLCODE != -2024 THEN
          RAISE;
        END IF;
    END;
    

    Materialized View

    BEGIN
      EXECUTE IMMEDIATE 'DROP MATERIALIZED VIEW ' || mview_name;
    EXCEPTION
      WHEN OTHERS THEN
        IF SQLCODE != -12003 THEN
          RAISE;
        END IF;
    END;
    

    Type

    BEGIN
      EXECUTE IMMEDIATE 'DROP TYPE ' || type_name;
    EXCEPTION
      WHEN OTHERS THEN
        IF SQLCODE != -4043 THEN
          RAISE;
        END IF;
    END;
    

    Constraint

    BEGIN
      EXECUTE IMMEDIATE 'ALTER TABLE ' || table_name
                || ' DROP CONSTRAINT ' || constraint_name;
    EXCEPTION
      WHEN OTHERS THEN
        IF SQLCODE != -2443 AND SQLCODE != -942 THEN
          RAISE;
        END IF;
    END;
    

    Scheduler Job

    BEGIN
      DBMS_SCHEDULER.drop_job(job_name);
    EXCEPTION
      WHEN OTHERS THEN
        IF SQLCODE != -27475 THEN
          RAISE;
        END IF;
    END;
    

    User / Schema

    BEGIN
      EXECUTE IMMEDIATE 'DROP USER ' || user_name;
      /* you may or may not want to add CASCADE */
    EXCEPTION
      WHEN OTHERS THEN
        IF SQLCODE != -1918 THEN
          RAISE;
        END IF;
    END;
    

    Package

    BEGIN
      EXECUTE IMMEDIATE 'DROP PACKAGE ' || package_name;
    EXCEPTION
      WHEN OTHERS THEN
        IF SQLCODE != -4043 THEN
          RAISE;
        END IF;
    END;
    

    Procedure

    BEGIN
      EXECUTE IMMEDIATE 'DROP PROCEDURE ' || procedure_name;
    EXCEPTION
      WHEN OTHERS THEN
        IF SQLCODE != -4043 THEN
          RAISE;
        END IF;
    END;
    

    Function

    BEGIN
      EXECUTE IMMEDIATE 'DROP FUNCTION ' || function_name;
    EXCEPTION
      WHEN OTHERS THEN
        IF SQLCODE != -4043 THEN
          RAISE;
        END IF;
    END;
    

    Tablespace

    BEGIN
      EXECUTE IMMEDIATE 'DROP TABLESPACE' || tablespace_name;
    EXCEPTION
      WHEN OTHERS THEN
        IF SQLCODE != -959 THEN
          RAISE;
        END IF;
    END;
    

    Synonym

    BEGIN
      EXECUTE IMMEDIATE 'DROP SYNONYM ' || synonym_name;
    EXCEPTION
      WHEN OTHERS THEN
        IF SQLCODE != -1434 THEN
          RAISE;
        END IF;
    END;
    
    0 讨论(0)
  • 2020-11-22 14:10

    I prefer to specify the table and the schema owner.

    Watch out for case sensitivity as well. (see "upper" clause below).

    I threw a couple of different objects in to show that is can be used in places besides TABLEs.

    .............

    declare
       v_counter int;
    begin
     select count(*) into v_counter from dba_users where upper(username)=upper('UserSchema01');
       if v_counter > 0 then
          execute immediate 'DROP USER UserSchema01 CASCADE';
       end if; 
    end;
    /
    
    
    
    CREATE USER UserSchema01 IDENTIFIED BY pa$$word
      DEFAULT TABLESPACE users
      TEMPORARY TABLESPACE temp
      QUOTA UNLIMITED ON users;
    
    grant create session to UserSchema01;  
    

    And a TABLE example:

    declare
       v_counter int;
    begin
     select count(*) into v_counter from all_tables where upper(TABLE_NAME)=upper('ORDERS') and upper(OWNER)=upper('UserSchema01');
       if v_counter > 0 then
          execute immediate 'DROP TABLE UserSchema01.ORDERS';
       end if; 
    end;
    /   
    
    0 讨论(0)
提交回复
热议问题