在Oracle中创建表之前检查表是否存在

quhf5bfb  于 2023-06-22  发布在  Oracle
关注(0)|答案(9)|浏览(178)

在Oracle中创建表之前,正在尝试检查表是否存在。搜索Stackoverflow和其他网站的大部分帖子。找到一些查询,但它没有为我工作。

IF((SELECT count(*) FROM dba_tables where table_name = 'EMPLOYEE') <= 0)
THEN
create table EMPLOYEE
(
ID NUMBER(3),
NAME VARCHAR2(30) NOT NULL
)
END IF;

这给了我错误

Error: ORA-00900: invalid SQL statement
SQLState:  42000
ErrorCode: 900
Position: 1

我搜索IF条件的语法,我认为这也是写的。请建议我……

rnmwe5a2

rnmwe5a21#

正如Rene所评论的那样,先检查然后创建表的情况非常少见。如果你想根据你的方法有一个运行的代码,这将是:

declare
  nCount number;
  v_sql clob;
begin
  select count(*) into nCount from dba_tables where table_name = 'EMPLOYEE';

  if ncount <= 0 then
    v_sql := '
      create table employee
      (
        id number,
        name varchar2(30) not null
      )';

    execute immediate v_sql;

  end if;
end;
/

但我宁愿去捕捉异常,节省一些不必要的代码行:

declare
  v_sql clob;
begin
  v_sql := '
    create table employee
    (
      id number,
      name varchar2(30) not null
    )';

  execute immediate v_sql;
exception
  when others then
    if sqlcode = -955 then
      null; -- suppresses ora-00955 exception
    else
      raise;
  end if;
end; 
/

从Oracle 23c开始,您可以使用更简单的IF NOT EXISTS语法:

create table if not exists employee
(
  id number,
  name varchar2(30) not null
);
mlmc2os5

mlmc2os52#

我知道这个主题有点老了,但我想我做了一些可能对某人有用的事情,所以我把它贴出来。
我将这个帖子的答案中的建议编译成一个过程:

CREATE OR REPLACE PROCEDURE create_table_if_doesnt_exist(
  p_table_name VARCHAR2,
  create_table_query VARCHAR2
) AUTHID CURRENT_USER IS
  n NUMBER;
BEGIN
  SELECT COUNT(*) INTO n FROM user_tables WHERE table_name = UPPER(p_table_name);
  IF (n = 0) THEN
    EXECUTE IMMEDIATE create_table_query;
  END IF;
END;

然后,您可以按以下方式使用它:

call create_table_if_doesnt_exist('my_table', 'CREATE TABLE my_table (
        id NUMBER(19) NOT NULL PRIMARY KEY,
        text VARCHAR2(4000),
        modified_time TIMESTAMP
  )'
);

我知道传递两次表名有点多余,但我认为这是最简单的。
希望有人发现上面有用:-)。

yb3bgrhw

yb3bgrhw3#

我的解决方案只是在线程中编译最好的想法,有一点改进。我使用专用过程(@Tomasz Borowiec)来促进重用,并使用异常处理(@Tobias Twardon)来减少代码并消除过程中的冗余表名。

DECLARE

    PROCEDURE create_table_if_doesnt_exist(
        p_create_table_query VARCHAR2
    ) IS
    BEGIN
        EXECUTE IMMEDIATE p_create_table_query;
    EXCEPTION
        WHEN OTHERS THEN
        -- suppresses "name is already being used" exception
        IF SQLCODE = -955 THEN
            NULL; 
        END IF;
    END;

BEGIN
    create_table_if_doesnt_exist('
        CREATE TABLE "MY_TABLE" (
            "ID" NUMBER(19) NOT NULL PRIMARY KEY,
            "TEXT" VARCHAR2(4000),
            "MOD_TIME" TIMESTAMP DEFAULT CURRENT_TIMESTAMP
        )
    ');
END;
/
zvms9eto

zvms9eto4#

请尝试:

SET SERVEROUTPUT ON
DECLARE
v_emp int:=0;
BEGIN
  SELECT count(*) into v_emp FROM dba_tables where table_name = 'EMPLOYEE'; 

  if v_emp<=0 then
     EXECUTE IMMEDIATE 'create table EMPLOYEE ( ID NUMBER(3), NAME VARCHAR2(30) NOT NULL)';
  end if;
END;
j91ykkif

j91ykkif5#

declare n number(10);

begin
   select count(*) into n from tab where tname='TEST';

   if (n = 0) then 
      execute immediate 
      'create table TEST ( ID NUMBER(3), NAME VARCHAR2 (30) NOT NULL)';
   end if;
end;
mbskvtky

mbskvtky6#

任何依赖于在创建之前进行测试的解决方案都可能会遇到“竞争”情况,即另一个进程在您测试该表不存在和创建它之间创建该表。- 我知道这点

xnifntxz

xnifntxz7#

--检查特定模式中的表:

declare n number(10);

begin
    Select count(*) into n  from SYS.All_All_Tables where owner = 'MYSCHEMA' and TABLE_NAME =  'EMPLOYEE';

   if (n = 0) then 
     execute immediate 
     'create table MYSCHEMA.EMPLOYEE ( ID NUMBER(3), NAME VARCHAR2(30) NOT NULL)';      
   end if;
end;
mzmfm0qo

mzmfm0qo8#

好吧,已经有很多答案了,很多都是有意义的。
有些人提到它只是警告,有些人给出了一个临时的方法来禁用警告。所有这些都可以工作,但当数据库中的事务数很高时,会增加风险
我今天遇到了类似的情况,这里是***非常简单的查询***我想出了…

declare
begin
  execute immediate '
    create table "TBL" ("ID" number not null)';
  exception when others then
    if SQLCODE = -955 then null; else raise; end if;
end;
/

955是失败代码。

这很简单,如果在运行查询时出现异常,它将被抑制。你可以使用相同的SQLOracle

lrl1mhuk

lrl1mhuk9#

它不需要申报和计数也适用。

begin
for rec in (select 1 from user_tables where table_name = 'YOUR_TABLE')
-- or
-- for rec in (select 1 from all_tables where table_name = 'YOUR_TABLE' and owner = 'YOU')
loop
    execute immediate 'create table your_table as (f1 char(1))';
end loop;
end;
/

将好的模式创建检查功能

create or replace function this_object_exists (p_obj_name user_objects.object_name%type) return boolean
is
begin
   for rec in (select 1 from user_objects where object_name = upper(p_obj_name))
   loop
        return true;
   end loop;
   return false;
end this_object_exists;

并因此使用代码检查是否存在
| .|.|.|.|
| - -----|- -----|- -----|- -----|
| 索引分区|表子分区|序列|表分区|
| 程序|LOB分区|LOB|索引细分|
| Package | Package 体|类型主体|触发器|
| 联系我们|表格|浏览|功能|
| 同义词|类型|工作|......这是什么?|

begin
if not this_object_exists('your_table') then
    execute immediate 'create table your_table as (f1 char(1))';
end if;
end;

begin
if this_object_exists('your_table') then
    execute immediate 'drop table your_table';
end if;
execute immediate 'create table your_table as (f1 char(1))';
end;

相关问题