Oracle: als de tabel

Ik schrijf wat migratiescripts voor een Oracle-database en hoopte Oracle iets vergelijkbaars met MySQL’s IF EXISTSConstruct.

Specifiek, wanneer ik een tafel in MySQL wil laten vallen, doe ik iets als

DROP TABLE IF EXISTS `table_name`;

Op deze manier, als de tabel niet bestaat, maakt de DROPgeen fout en kan het script doorgaan.

Heeft Oracle een vergelijkbaar mechanisme? Ik realiseer me dat ik de volgende zoekopdracht zou kunnen gebruiken om te controleren of een tabel bestaat of niet

SELECT * FROM dba_tables where table_name = 'table_name';

Maar de syntaxis voor het binden van dat samen met een DROPis ontsnapt.


Antwoord 1, Autoriteit 100%

De beste en meest efficiënte manier is om de “tabel niet gevonden” uitzondering te vangen: dit vermijdt de overhead van controle als de tabel twee keer bestaat; en lijdt niet aan het probleem dat als de daling faalt om een ​​andere reden (die belangrijk kan zijn), de uitzondering wordt nog steeds verhoogd naar de beller:

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

addendum
Ter referentie, hier zijn de equivalente blokken voor andere objecttypen:

Sequence

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

Bekijken

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;

kolom

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;

Materialiseerd weergave

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;

beperking

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;

Planner-taak

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

Gebruiker / 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;

Pakket

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;

Functie

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

Tabelruimte

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

Synoniem

BEGIN
  EXECUTE IMMEDIATE 'DROP SYNONYM ' || synonym_name;
EXCEPTION
  WHEN OTHERS THEN
    IF SQLCODE != -1434 THEN
      RAISE;
    END IF;
END;

Antwoord 2, Autoriteit 24%

declare
   c int;
begin
   select count(*) into c from user_tables where table_name = upper('table_name');
   if c = 1 then
      execute immediate 'drop table table_name';
   end if;
end;

Dat is voor het controleren of er een tafel in het huidige schema bestaat.
Om te controleren of een bepaalde tabel al in een ander schema bestaat, zou u all_tablesgebruiken in plaats van user_tablestoevoegen en de voorwaarde toevoegen all_tables.owner = upper('schema_name')


Antwoord 3, Autoriteit 5%

Ik ben op zoek naar hetzelfde, maar ik heb uiteindelijk een procedure aan het schrijven om me te helpen:

CREATE OR REPLACE PROCEDURE DelObject(ObjName varchar2,ObjType varchar2)
IS
 v_counter number := 0;   
begin    
  if ObjType = 'TABLE' then
    select count(*) into v_counter from user_tables where table_name = upper(ObjName);
    if v_counter > 0 then          
      execute immediate 'drop table ' || ObjName || ' cascade constraints';        
    end if;   
  end if;
  if ObjType = 'PROCEDURE' then
    select count(*) into v_counter from User_Objects where object_type = 'PROCEDURE' and OBJECT_NAME = upper(ObjName);
      if v_counter > 0 then          
        execute immediate 'DROP PROCEDURE ' || ObjName;        
      end if; 
  end if;
  if ObjType = 'FUNCTION' then
    select count(*) into v_counter from User_Objects where object_type = 'FUNCTION' and OBJECT_NAME = upper(ObjName);
      if v_counter > 0 then          
        execute immediate 'DROP FUNCTION ' || ObjName;        
      end if; 
  end if;
  if ObjType = 'TRIGGER' then
    select count(*) into v_counter from User_Triggers where TRIGGER_NAME = upper(ObjName);
      if v_counter > 0 then          
        execute immediate 'DROP TRIGGER ' || ObjName;
      end if; 
  end if;
  if ObjType = 'VIEW' then
    select count(*) into v_counter from User_Views where VIEW_NAME = upper(ObjName);
      if v_counter > 0 then          
        execute immediate 'DROP VIEW ' || ObjName;        
      end if; 
  end if;
  if ObjType = 'SEQUENCE' then
    select count(*) into v_counter from user_sequences where sequence_name = upper(ObjName);
      if v_counter > 0 then          
        execute immediate 'DROP SEQUENCE ' || ObjName;        
      end if; 
  end if;
end;

Hopelijk helpt dit


Antwoord 4, autoriteit 2%

ik wilde gewoon een volledige code posten die een tabel maakt en deze verwijdert als deze al bestaat met behulp van Jeffrey’s code (kudos aan hem, niet aan mij!).

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;

Antwoord 5, autoriteit 2%

Met SQL*PLUS kunt u ook de opdracht WHENEVER SQLERROR gebruiken:

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

Met CONTINUE NONEwordt een fout gerapporteerd, maar het script gaat door. Met EXIT SQL.SQLCODEwordt het script beëindigd in het geval van een fout.

zie ook: WANNEER SQLERROR Documenten


Antwoord 6

Ik geef de voorkeur aan de volgende economische oplossing

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;

Antwoord 7

Een andere methode is om een uitzondering te definiëren en die uitzondering dan alleen op te vangen en alle anderen te laten verspreiden.

Declare
   eTableDoesNotExist Exception;
   PRAGMA EXCEPTION_INIT(eTableDoesNotExist, -942);
Begin
   EXECUTE IMMEDIATE ('DROP TABLE myschema.mytable');
Exception
   When eTableDoesNotExist Then
      DBMS_Output.Put_Line('Table already does not exist.');
End;

Antwoord 8

Er is geen ‘DROP TABLE IF EXISTS’ in oracle, je zou de select-opdracht moeten doen.

probeer dit (ik ben niet op de hoogte van de oracle-syntaxis, dus als mijn variabelen ify zijn, vergeef me alstublieft):

declare @count int
select @count=count(*) from all_tables where table_name='Table_name';
if @count>0
BEGIN
    DROP TABLE tableName;
END

Antwoord 9

Een manier is om DBMS_ASSERT.SQL_OBJECT_NAME :

Deze functie controleert of de invoerparameterreeks een gekwalificeerde SQL-identificatie is van een bestaand SQL-object.

DECLARE
    V_OBJECT_NAME VARCHAR2(30);
BEGIN
   BEGIN
        V_OBJECT_NAME  := DBMS_ASSERT.SQL_OBJECT_NAME('tab1');
        EXECUTE IMMEDIATE 'DROP TABLE tab1';
        EXCEPTION WHEN OTHERS THEN NULL;
   END;
END;
/

DBFiddle-demo


Antwoord 10

En als u het opnieuw toegankelijk wilt maken en drop/create-cycli wilt minimaliseren, kunt u de DDL cachen met behulp van dbms_metadata.get_ddl en alles opnieuw maken met een constructie als deze:

declare
v_ddl varchar2(4000);
begin
select dbms_metadata.get_ddl('TABLE','DEPT','SCOTT') into v_ddl from dual;
[COMPARE CACHED DDL AND EXECUTE IF NO MATCH]
exception when others then
if sqlcode = -31603 then
[GET AND EXECUTE CACHED DDL]
else
raise;
end if;
end;

Dit is slechts een voorbeeld, er zou een lus in moeten zitten met DDL-type, naam en eigenaar als variabelen.


Antwoord 11

Een blok als dit kan nuttig voor je zijn.

DECLARE
    table_exist INT;
BEGIN
    SELECT Count(*)
    INTO   table_exist
    FROM   dba_tables
    WHERE  owner = 'SCHEMA_NAME' 
    AND table_name = 'EMPLOYEE_TABLE';
    IF table_exist = 1 THEN
      EXECUTE IMMEDIATE 'drop table EMPLOYEE_TABLE';
    END IF;
END;  

Antwoord 12

Helaas nee, er bestaat niet zoiets als laten vallen als het bestaat, of MAKEN ALS HET NIET BESTAAT

Je zou een plsql-script kunnen schrijven om de logica daar op te nemen.

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

Ik ben niet veel in Oracle Syntax, maar ik denk dat het script van @ Erich zoiets zou zijn.

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;

Antwoord 13

U kunt zelf altijd de fout vangen.

begin
execute immediate 'drop table mytable';
exception when others then null;
end;

Het wordt beschouwd als een slechte praktijk om dit te overhandelen, vergelijkbaar met lege vangst () ‘es in andere talen.

Met vriendelijke groeten
K


Antwoord 14

Ik geef er de voorkeur aan om de tabel en de schema-eigenaar op te geven.

Pas op voor geval van gevoeligheid. (zie “Bovenste” -clausule hieronder).

Ik gooide een paar verschillende objecten in om te laten zien dat het op plaatsen behalve tabellen kan worden gebruikt.

………….

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;  

en een tabelvoorbeeld:

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;
/   

Antwoord 15

BEGIN
   EXECUTE IMMEDIATE 'DROP TABLE "IMS"."MAX" ';
EXCEPTION
   WHEN OTHERS THEN
      IF SQLCODE != -942 THEN
         RAISE;
          END IF;
         EXECUTE IMMEDIATE ' 
  CREATE TABLE "IMS"."MAX" 
   (    "ID" NUMBER NOT NULL ENABLE, 
    "NAME" VARCHAR2(20 BYTE), 
     CONSTRAINT "MAX_PK" PRIMARY KEY ("ID")
  USING INDEX PCTFREE 10 INITRANS 2 MAXTRANS 255 
  STORAGE(INITIAL 65536 NEXT 1048576 MINEXTENTS 1 MAXEXTENTS 2147483645
  PCTINCREASE 0 FREELISTS 1 FREELIST GROUPS 1 BUFFER_POOL DEFAULT FLASH_CACHE DEFAULT CELL_FLASH_CACHE DEFAULT)
  TABLESPACE "SYSAUX"  ENABLE
   ) SEGMENT CREATION IMMEDIATE 
  PCTFREE 10 PCTUSED 40 INITRANS 1 MAXTRANS 255 NOCOMPRESS LOGGING
  STORAGE(INITIAL 65536 NEXT 1048576 MINEXTENTS 1 MAXEXTENTS 2147483645
  PCTINCREASE 0 FREELISTS 1 FREELIST GROUPS 1 BUFFER_POOL DEFAULT FLASH_CACHE DEFAULT CELL_FLASH_CACHE DEFAULT)
  TABLESPACE "SYSAUX"  ';
END;

// controleert deze code of de tabel bestaat en later maakt het de tabel max. Dit werkt eenvoudig in enkele compilatie

Other episodes