首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >如何创建表并在同一语句中插入

如何创建表并在同一语句中插入
EN

Stack Overflow用户
提问于 2013-08-14 09:17:29
回答 3查看 1.8K关注 0票数 1

我刚开始接触甲骨文,我正在努力解决这个问题:

代码语言:javascript
运行
复制
DECLARE 
 cnt NUMBER;

BEGIN
 SELECT COUNT(*) INTO cnt FROM all_tables WHERE table_name like 'Newtable'; 
 IF(cnt=0) THEN
   EXECUTE IMMEDIATE 'CREATE TABLE Newtable ....etc';
 END IF;
 COMMIT;

 SELECT COUNT(*) INTO cnt FROM Newtable where id='something'
 IF (cnt=0) THEN
   EXECUTE IMMEDIATE 'INSERT INTO Newtable ....etc';
 END IF;
END;

这会持续崩溃,给我插入行上的"PL/SQL: ORA-00942:table或view不存在“。我怎么才能避免这种情况?或者我做错什么了?我希望这两个语句(在现实中,这是更多的,当然)在一个事务。

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2013-08-14 14:10:49

问题不在于insert,而是前面两行的select。在块中有三条语句,而不是两条。您正在从还不存在的同一个新表中进行选择。您可以在insert中通过动态操作来避免这种情况,但是您需要对select进行相同的操作:

代码语言:javascript
运行
复制
 EXECUTE IMMEDIATE q'[SELECT COUNT(*) FROM Newtable where id='something']'
 INTO cnt;

SQL Fiddle

不过,在运行时创建表似乎是错误的。您说过,“为了安全问题,表只有在填充正确的数据集时才能存在”,这对我来说没有任何意义--即使这个块是一次创建和填充它,任何依赖它的东西都会失败或者在运行之前失效。如果这是模式创建的一部分,那么使其动态化似乎不会增加太多内容。您还说希望这两种情况都发生在一个事务中,但是DDL将执行隐式提交,您不能回滚DDL,而且手动提交将为insert(s)启动一个新事务。也许您的意思是,如果表创建失败,插入就不应该发生--但无论如何,它们都会失败,不管它们是否位于同一个块中。不管怎样,这似乎有点奇怪。

而且,使用all_tables进行检查仍然会导致这种行为异常。如果该表存在于另一个模式中,则将跳过create,但您的selectinsert仍然可能会失败,因为它们可能无法看到或不会查找其他模式版本。使用user_tables或添加owner检查可能会更安全一些。

票数 4
EN

Stack Overflow用户

发布于 2013-08-14 10:24:18

尝试以下方法,即在两个不同的块中创建和插入

代码语言:javascript
运行
复制
DECLARE
    cnt NUMBER;
BEGIN
    SELECT  COUNT (*)
      INTO  cnt
      FROM  all_tables
     WHERE  table_name LIKE 'Newtable';

    IF (cnt = 0)
    THEN
        EXECUTE IMMEDIATE 'CREATE TABLE Newtable(c1 varchar2(256))';
    END IF;
END;

DECLARE
    cnt2    NUMBER;
BEGIN
    SELECT  COUNT (*)
      INTO  cnt2
      FROM  newtable
     WHERE  c1 = 'jack';

    IF (cnt2 = 0)
    THEN
        EXECUTE IMMEDIATE 'INSERT INTO Newtable values(''jill'')';
    END IF;
END;
票数 0
EN

Stack Overflow用户

发布于 2013-08-14 14:22:14

Oracle分两个步骤处理块的执行:

  1. 首先,它解析该块并将其编译为内部表示形式(称为"P代码“)。
  2. 然后运行P代码(根据您的体系结构和Oracle版本,可以将其解释或编译为机器代码)

为了编译代码,Oracle必须知道名称(和模式!)引用的表格。您的表还不存在,因此没有模式,代码也没有编译。

在一个大事务中创建表的意图:这是行不通的。甲骨文总是在DDL语句之前和之后隐式提交当前事务。 (create tablealter tabletruncate table(!)等等)。因此,在每个create table之后,Oracle将提交当前事务并启动一个新事务。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/18227662

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档