你能把一个CREATE TABLE语句放在PL / SQL块中吗?

问题描述 投票:0回答:4

我正在尝试编写一些代码以在创建表之前检查表是否存在。首先,我试图运行以下内容:

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之间有区别吗?

database oracle plsql
4个回答
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;

4
投票

是的,您可以使用动态SQL,即EXECUTE IMMEDIATE。

但是,请三思而后行 - 以这种方式创建表格并不常见。你为什么要这样做?


3
投票

oracle抛出的常见异常是“ORA-00955:名称已被现有对象使用”。但仅此一点不足以说明该表已经创建。由于在同一命名空间内,没有两个对象可以具有相同的名称:

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

因此异常消息:“名称已被现有对象使用”

但是如果您知道这一点并想要一个匿名的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;
© www.soinside.com 2019 - 2024. All rights reserved.