36

在 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,我认为这也是写的。请建议我....

4

9 回答 9

42

正如 Rene 还评论的那样,先检查然后创建表的情况很少见。如果您想根据您的方法运行代码,这将是:

declare
nCount NUMBER;
v_sql LONG;

begin
SELECT count(*) into nCount FROM dba_tables where table_name = 'EMPLOYEE';
IF(nCount <= 0)
THEN
v_sql:='
create table EMPLOYEE
(
ID NUMBER(3),
NAME VARCHAR2(30) NOT NULL
)';
execute immediate v_sql;

END IF;
end;

但我宁愿抓住异常,为您节省一些不必要的代码行:

declare
v_sql LONG;
begin

v_sql:='create table EMPLOYEE
  (
  ID NUMBER(3),
  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; 
/
于 2013-03-26T09:16:14.850 回答
7

我知道这个话题有点老了,但我认为我做了一些可能对某人有用的事情,所以我发布了它。

我将此线程的答案中的建议编译成一个过程:

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
  )'
);

我知道两次传递表名有点多余,但我认为这是最简单的。

希望有人发现上面有用:-)。

于 2016-11-03T15:52:18.907 回答
2

请试试:

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;
于 2013-03-26T06:56:52.207 回答
2
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;
于 2016-01-23T20:43:25.293 回答
2

我的解决方案只是在线程中汇总最佳想法,并稍作改进。我使用专用过程 (@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;
/
于 2018-06-13T14:14:27.757 回答
1

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

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;
于 2019-05-17T14:09:11.387 回答
1

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

于 2018-09-28T05:15:03.447 回答
1

好吧,已经提供了很多答案,而且很多答案也很有意义。

有些人提到这只是警告,有些人提供了一种临时方法来禁用警告。当您的数据库中的事务数量很高时,所有这些都会起作用,但会增加风险。

我今天遇到了类似的情况,这是我想出的非常简单的查询...

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 是故障代码。

这很简单,如果在运行查询时出现异常,它将被抑制。并且您可以将其用于SQLor Oracle

于 2020-04-23T11:19:53.957 回答
0

它也不需要声明和计数。

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 分区 高球 索引子分区
包裹 包体 正文 扳机
指数 桌子 看法 功能
代名词 类型 工作 ...
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;
于 2021-05-16T09:24:32.583 回答