不存在则创建表,创建后输入一行

Posted

技术标签:

【中文标题】不存在则创建表,创建后输入一行【英文标题】:Create table if it does not exist, and enter one row after creating 【发布时间】:2015-05-29 09:08:31 【问题描述】:

如果表不存在,我需要创建一个表,并在创建时添加一行。

我是 oracle 和 PL/SQL 的新手,所以我基本上需要以下 T-SQL 的等效项:

IF OBJECT_ID('my_table', 'U') IS NULL
BEGIN
  CREATE TABLE my_table(id numeric(38,0), date datetime)    
  INSERT INTO my_table
  VALUES (NULL, 0)
END

【问题讨论】:

这个要求背后的原因是什么?这是一个家庭作业问题吗?通常,您不应该在 PL/SQL 中创建表 - 表是永久对象,应该创建一次,然后在任何代码中使用。如果您要临时存储数据的表,请考虑创建一个全局临时表 (GTT),这是一个永久表,允许在每个会话的基础上临时存储数据(即会话 2 看不到会话 1 存储的 GTT 中的数据,反之亦然)。 它就像你在使用 sybase 语法 【参考方案1】:

如果你想检查表的创建

DECLARE count NUMBER;
BEGIN
count := 0;
SELECT COUNT(1) INTO count from user_tables WHERE table_name= 'MY_TABLE';
IF COL_COUNT = 0 THEN
EXECUTE IMMEDIATE 'create table ....';
END IF;
END;
/

检查DML。请注意,您必须对您的 pk 列和值进行 sepcify。

DECLARE count NUMBER;
BEGIN
count := 0;
SELECT COUNT(1) INTO count from MY_TABLE WHERE id= 0 and name='Something';
IF COL_COUNT = 0 THEN
EXECUTE IMMEDIATE 'insert into MY_TABLE (id,name) values(0,''something'') ';
END IF;
END;
/

另请注意,我建议您在插入表格时指定列

【讨论】:

也许还值得展示插入也必须动态完成? (并且将 col_count - 您的名称不一致! - 设置为零是多余的。) @AlexPoole 好吧我添加检查插入 我的意思是在同一个块中,直接在动态创建之后。在单独的块中不太有意义;如果选择有效(因为表现在存在),那么插入不需要是动态的。但是 OP 似乎想将创建/插入作为一个步骤;所以你会将两个execute immediate 语句放在第一个块中? @AlexPoole 我的意思是提供更好的方法?无论如何我要把它放在一个块中 更好的方法是拥有一张永久的桌子,根本不必这样做*8-)【参考方案2】:

另一种方法是使用异常逻辑。我根据Oracle规则更改了字段名称和类型

declare
  eAlreadyExists exception;
  pragma exception_init(eAlreadyExists, -00955);
begin
  execute immediate 'CREATE TABLE my_table(id number, dateof date)';
  execute immediate 'INSERT INTO my_table VALUES (NULL, sysdate)';
  exception when eAlreadyExists then 
      null;  
end;

但动态创建表可能不是一个好主意

【讨论】:

但动态创建表可能不是一个好主意我同意但只是好奇,你对为什么不动态创建表的解释是什么?【参考方案3】:

在我看来,您不应该即时创建对象。您应该在实施之前考虑您的设计。

无论如何,如果您真的想这样做,那么您需要在 PL/SQL (ab) 中使用 EXECUTE IMMEDIATE 以编程方式进行。

但是,如果您想用单行创建一个表,我更喜欢 CTAScreate table as select。例如,

SQL> CREATE TABLE t AS SELECT 1 id, SYSDATE dt FROM DUAL;

Table created.

SQL> SELECT * FROM t;

        ID DT
---------- ---------
         1 29-MAY-15

SQL>

该表是永久创建的。

如果您正在寻找可用于存储会话特定数据的临时表,请查看creating Global temporary table

来自文档,

使用 CREATE GLOBAL TEMPORARY TABLE 语句创建临时 桌子。 ON COMMIT 子句指示表中的数据是否为 特定于事务(默认)或特定于会话

【讨论】:

【参考方案4】:

您可以将NOT EXISTS 与 select 语句一起使用:

IF NOT EXISTS(SELECT 1 FROM my_table) THEN
CREATE TABLE my_table(id NUMBER, date date);
COMMIT;
INSERT INTO my_table(id, date) values (NULL, O);
COMMIT;
END IF;

更新

根据评论,我不能直接在 PL/SQL 中使用 Exist。所以这是另一种方法:

begin
  select case
           when exists(select 1
                         from my_table)
           then 1
           else 0
        end into l_exists
   from dual;

  if (l_exists = 1)
  then
    -- anything
  else
     EXECUTE IMMEDIATE 'CREATE TABLE my_table(id NUMBER, date date)';
     EXECUTE IMMEDIATE 'INSERT INTO my_table(id, date) values (NULL, O)';
  end if;
 end;

【讨论】:

不,你不能;无论如何,你不能在纯 SQL 中使用IF,但如果你可以,SELECT 1 FROM my_table 仍然会得到 ORA-00942。如果您在 PL/SQL 块中执行此操作,则必须动态创建和插入,并且您也不能直接在 PL/SQL 中使用exists,只能在 SQL 中使用。 @AlexPoole 谢谢。我已经建议了另一种方法。 嗯。您是否尝试过您的解决方案? :) 正如@AlexPoole 所说,您的脚本将无法编译,因为 MY_TABLE 不存在。 IF 部分要么没有编译,但由于不同的原因,你忘记了声明等。你需要通过从 user_tables、all_objects 或类似的东西中选择来检查表的存在。所以 NOT EXISTS 是用于查询,而不是用于测试对象的存在性。

以上是关于不存在则创建表,创建后输入一行的主要内容,如果未能解决你的问题,请参考以下文章

MYSQL:如果不存在则创建表

如果存在则更改表,如果不存在则创建

从 Excel VBA-检查访问表是不是存在/如果不存在,则创建/复制

mysql怎样实现" 如果表存在则清空,不存在则创建表"

PDO MYSQL 如果不存在则创建表并找出它是不是已创建

如果 Oracle 中不存在表,则创建一个表(使用 Java)