2017-12-15 14 views
0

テーブルを作成する前にテーブルが存在するかどうかを確認するためのコードを記述しようとしています。開始するには、次のコードを実行しようとしています。PL/SQLブロック内にCREATE TABLE文を置くことはできますか?

BEGIN 
create table IT.DEVOPS_UC_SERVER_REG_TABLE 
(
    agentname  VARCHAR2(100) not null, 
    servername  VARCHAR2(100) not null, 
    datelastdeployed TIMESTAMP(6) WITH TIME ZONE, 
    technology  VARCHAR2(100) not null, 
    issetup   VARCHAR2(10) 
); 
EXCEPTION 
    NULL; 
END;/ 

ただし、これは有効なPL/SQLコードではないようです。誰がなぜこのような場合があるのか​​知っていますか? PL/SQLのDDLとDMLの違いはありますか?

+2

'exception'ブロックが不正です。あなたが意味していれば、 '...他の人がnullになった時の例外。 ...、それをやめて!! –

+0

PL/SQLはDDLではなくDMLのみを解析します。そのため、DDLを文字列にラップしてSQLエンジンに渡す必要があります。 EXECUTE IMMEDIATEおよびDBMS_SQLは、そうするための2つの方法です。 –

+0

plsqlブロックにテーブルを作成する必要はありません。 ddlは通常作成され、単独で実行されます。 s.oにはいくつかの例があります。これをplsqlブロックで行う必要がある場合。 –

答えて

2

あなたは、このようにブロックを使用する必要があります。

DECLARE 
    L_CNT PLS_INTEGER; 
BEGIN 
    SELECT COUNT(0) 
    INTO L_CNT 
    FROM ALL_TABLES T 
    WHERE T.TABLE_NAME = 'DEVOPS_UC_SERVER_REG_TABLE' 
     AND T.OWNER = 'IT'; 

    IF L_CNT > 0 THEN 
    RETURN; 
    END IF; 

EXECUTE IMMEDIATE 'create table IT.DEVOPS_UC_SERVER_REG_TABLE' || chr(10) || 
        '(' || chr(10) || 
        ' agentname  VARCHAR2(100) not null,' || chr(10) || 
        ' servername  VARCHAR2(100) not null,' || chr(10) || 
        ' datelastdeployed TIMESTAMP(6) WITH TIME ZONE,' || chr(10) || 
        ' technology  VARCHAR2(100) not null,' || chr(10) || 
        ' issetup   VARCHAR2(10)' || chr(10) || 
        ')'; 

END; 
+0

"all_tables"を使用した良い提案 –

+0

すべての回答は素晴らしく、すべてをアップしましたが、それは非常にエレガントな方法で例外を回避し、ALL_TABLESについてのことを説明しているからです –

4

はい、動的SQLを使用して実行することができます。つまり、EXECUTE IMMEDIATEです。

しかし、そのようにテーブルを作成することは普通ではありません。なぜあなたはそれをしたいのですか?

3

Oracleがスローという共通の例外は、「ORA-00955:名前が既存のオブジェクトによって使用されている」です。しかしこれだけでは、テーブルがすでに作成されていることを伝えるには不十分です。したがって

https://docs.oracle.com/database/121/SQLRF/sql_elements008.htm#i78631

例外メッセージ:

しかし、あなたならば「名前は、すでに既存のオブジェクトによって使用されている」原因同じ名前空間内、どの2つのオブジェクトが同じ名前を持つことはできませんという事実にそれを認識しており、匿名のpl/sqlブロックが必要です。

declare 
    lc__ constant varchar2(100) := 'Anonymous PL/SQL Block'; 
    already_created exception; 
    pragma exception_init(already_created, -955); -- ORA-00955: name is already used by an existing object 
    lv_stmt   varchar2(32767); 
begin 
    lv_stmt := q'[create table it.devops_uc_server_reg_table (
        agentname  varchar2(100) not null, 
        servername  varchar2(100) not null, 
        datelastdeployed timestamp(6) with time zone, 
        technology  varchar2(100) not null, 
        issetup   varchar2(10)) 
       ]'; 
    begin 
    execute immediate lv_stmt; 
    exception 
    when already_created then 
     dbms_output.put_line('Name already defined on an existing object'); 
    when others then 
     raise; 
    end; 
exception when others then 
    raise_application_error(-20777, lc__ || chr(10) || dbms_utility.format_error_stack); 
end; 
1

ありがとうございました。私はそれらを組み合わせることにしました。これは私が最終的に使用したものです:

DECLARE 
    L_CNT PLS_INTEGER; 
    lv_stmt varchar2(32767); 
BEGIN 
    --Check if the table already exists 
    SELECT COUNT(0) 
    INTO L_CNT 
    FROM ALL_TABLES T 
    WHERE T.TABLE_NAME = 'DEVOPS_UC_SERVER_REG_TABLE' 
     AND T.OWNER = 'IT'; 
    IF L_CNT > 0 THEN 
    dbms_output.put_line('The table already exists'); 
    RETURN; 
    END IF; 

    --Check if the constraint already exists 
    SELECT COUNT(0) 
    INTO L_CNT 
    FROM ALL_CONSTRAINTS C 
    WHERE C.CONSTRAINT_NAME = 'DEVOPS_UC_Server_Reg_PKEY' 
     AND C.OWNER = 'IT'; 
    IF L_CNT > 0 THEN 
    dbms_output.put_line('The primary key constraint already exists'); 
    RETURN; 
    END IF; 

    dbms_output.put_line('Creating table...'); 


    /* 
this code is auto-generated from DBMS_METADATA. It was accessed using the following query: 

SELECT 
DBMS_METADATA.GET_DDL('TABLE','DEVOPS_UC_SERVER_REG_TABLE','IT') 
FROM DUAL; 

so long as the tables do not exist, and the PRIMARY KEY NAME does not already exist 
then this will create the table with the primary key constraint. 
otherwise, you will run into ORA-0095: name already used by existing object (if table exists) 
or ORA-02264: name already used by an existing constraint 
TODO: make the table name and primary key constraint name variables for ease of use/robustness 
*/ 
    lv_stmt:=q'[ 
    CREATE TABLE "IT"."DEVOPS_UC_SERVER_REG_TABLE" 
    ( "AGENTNAME" VARCHAR2(100 CHAR) NOT NULL ENABLE, 
    "SERVERNAME" VARCHAR2(100 CHAR) NOT NULL ENABLE, 
    "DATELASTDEPLOYED" TIMESTAMP (6) WITH TIME ZONE, 
    "TECHNOLOGY" VARCHAR2(100 CHAR) NOT NULL ENABLE, 
    "ISSETUP" VARCHAR2(10 CHAR), 
    CONSTRAINT "DEVOPS_UC_Server_Reg_PKEY" PRIMARY KEY ("AGENTNAME", "SERVERNAME", "TECHNOLOGY") 
    USING INDEX PCTFREE 10 INITRANS 2 MAXTRANS 255 COMPUTE STATISTICS 
    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 "IT" 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 "IT" ]'; 

    execute immediate lv_stmt; 
dbms_output.put_line('Table created successfully'); 

END; 
関連する問題