我刚开始接触甲骨文,我正在努力解决这个问题:
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不存在“。我怎么才能避免这种情况?或者我做错什么了?我希望这两个语句(在现实中,这是更多的,当然)在一个事务。
发布于 2013-08-14 14:10:49
问题不在于insert,而是前面两行的select。在块中有三条语句,而不是两条。您正在从还不存在的同一个新表中进行选择。您可以在insert中通过动态操作来避免这种情况,但是您需要对select进行相同的操作:
EXECUTE IMMEDIATE q'[SELECT COUNT(*) FROM Newtable where id='something']'
INTO cnt;SQL Fiddle。
不过,在运行时创建表似乎是错误的。您说过,“为了安全问题,表只有在填充正确的数据集时才能存在”,这对我来说没有任何意义--即使这个块是一次创建和填充它,任何依赖它的东西都会失败或者在运行之前失效。如果这是模式创建的一部分,那么使其动态化似乎不会增加太多内容。您还说希望这两种情况都发生在一个事务中,但是DDL将执行隐式提交,您不能回滚DDL,而且手动提交将为insert(s)启动一个新事务。也许您的意思是,如果表创建失败,插入就不应该发生--但无论如何,它们都会失败,不管它们是否位于同一个块中。不管怎样,这似乎有点奇怪。
而且,使用all_tables进行检查仍然会导致这种行为异常。如果该表存在于另一个模式中,则将跳过create,但您的select和insert仍然可能会失败,因为它们可能无法看到或不会查找其他模式版本。使用user_tables或添加owner检查可能会更安全一些。
发布于 2013-08-14 10:24:18
尝试以下方法,即在两个不同的块中创建和插入
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;发布于 2013-08-14 14:22:14
Oracle分两个步骤处理块的执行:
为了编译代码,Oracle必须知道名称(和模式!)引用的表格。您的表还不存在,因此没有模式,代码也没有编译。
在一个大事务中创建表的意图:这是行不通的。甲骨文总是在DDL语句之前和之后隐式提交当前事务。 (create table,alter table,truncate table(!)等等)。因此,在每个create table之后,Oracle将提交当前事务并启动一个新事务。
https://stackoverflow.com/questions/18227662
复制相似问题