不存在则创建表,创建后输入一行
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 以编程方式进行。
但是,如果您想用单行创建一个表,我更喜欢 CTAS 即create 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 是用于查询,而不是用于测试对象的存在性。以上是关于不存在则创建表,创建后输入一行的主要内容,如果未能解决你的问题,请参考以下文章