Ik schrijf wat migratiescripts voor een Oracle-database en hoopte Oracle iets vergelijkbaars met MySQL’s IF EXISTS
Construct.
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 DROP
geen 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 DROP
is 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_tables
gebruiken in plaats van user_tables
toevoegen 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 NONE
wordt een fout gerapporteerd, maar het script gaat door. Met EXIT SQL.SQLCODE
wordt 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;
/
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