2012-10-24 48 views
-2

我有一个PL/SQL函数可以创建一个新的临时表。为了创建表格我使用execute immediate。当我在oracle sql developer中运行我的函数时,一切正常;该函数创建临时表而没有错误。但是,当U使用SQL:创建表并从sql中调用它

Select function_name from table_name 

我得到一个例外:

ORA-14552: cannot perform a DDL, commit or rollback inside a query or DML 
ORA-06512: at "SYSTEM.GET_USERS", line 10 
14552. 00000 - "cannot perform a DDL, commit or rollback inside a query or DML " 
*Cause: DDL operations like creation tables, views etc. and transaction 
     control statements such as commit/rollback cannot be performed 
     inside a query or a DML statement. 

更新

对不起,从平板电脑和写有格式的文本问题。我的功能:

CREATE OR REPLACE FUNCTION GET_USERS 
(
    USERID IN VARCHAR2 
) 
RETURN VARCHAR2 
AS 
    request VARCHAR2(520) := 'CREATE GLOBAL TEMPORARY TABLE '; 
BEGIN 
    request := request || 'temp_table_' || userid || 
      '(user_name varchar2(50), user_id varchar2(20), is_administrator varchar2(5)') || 
      ' ON COMMIT PRESERVE ROWS'; 
    EXECUTE IMMEDIATE (request); 
    RETURN 'true'; 
END GET_USERS; 
+1

有一些代码,我们没有看到?什么是第10行? – awright18

+2

使用编辑功能将代码添加到原始文章中,请勿将其添加为评论。 – GrandMasterFlush

+0

谢谢。快点,犯了一个错误。更正 – Arol

回答

0

我测试了以下解决方案上的Oracle 10g XE , 这个对我有用。

创建功能:

CREATE OR REPLACE FUNCTION GET_USERS 
(
    USERID IN VARCHAR2 
) 
RETURN VARCHAR2 
AS 
    request VARCHAR2(255) := 'CREATE GLOBAL TEMPORARY TABLE '; 
BEGIN 
    request := request || 'temp_table_' || userid || 
      '(user_name varchar2(50), user_id varchar2(20), is_administrator varchar2(5))' || 
      ' ON COMMIT PRESERVE ROWS'; 
    EXECUTE IMMEDIATE request; 
    RETURN 'true'; 
END GET_USERS; 

运行功能:

SET SERVEROUTPUT ON 
DECLARE 
RESULT VARCHAR(255); 
BEGIN 
    RESULT:=gET_USERS('ADMIN3'); 
    dbms_output.put_line(result); 
END; 

,并从临时表中选择:

SELECT * FROM temp_table_admin3; 
+0

感谢这个好讨论的,它的工作。 – Arol

+0

我很高兴,我可以帮助你。 – Parado

2

的错误是明确的:

ORA-14552:无法执行DDL,提交或回滚,在查询内部或DML

在Oracle中,你可以” t在查询内提交。一个可能的解释是,这是没有意义的,因为Oracle中的查询是原子的(完全成功或者没有改变),如果你在DML中间提交,这是行不通的。对于选择查询,必须从单个逻辑时间点返回所有行,并且如果在选择中间提交,则会产生不一致的结果。

由于Oracle中的DDL发出隐式提交,因此无法在查询中生成DDL。

尽管如此,这不应该成为问题:类似于SQL Server的临时表与Oracle中的临时表不相当于GLOBALY。有一个原因,为什么临时表中的临时表总是以GLOBALLY为前缀:尽管临时表中的数据对于每个会话都是私有的,但它们对所有会话均可见。

在Oracle中创建一个临时表是一个相对昂贵的操作,你不应该创建单独的临时表:所有执行同一工作的会话应该使用相同的通用结构。在Oracle中,您应该创建一次表并在所有过程中重复使用它,而不是创建多个临时表。如果你以后需要它,为什么要放弃它?

在任何情况下,如果你决定这样做,取决于选择多个DDL,你可以做一个PLSQL块,而不是一个SELECT查询:

DECLARE 
    l VARCHAR2(100); 
BEGIN 
    FOR cc IN (SELECT col FROM tab) LOOP 
     l := create_temp_table(cc.col); 
    END LOOP; 
END; 
+0

THX。我有一些不同的要求,requesr的每个结果都有不同的结构。我有任务:在db中执行所有请求,不要在客户端的请求中使用表和列名。对于没有长字符串的当前请求的结果,我为每个用户使用tmp表。对于来自user1的所有请求,我使用1个tmp-table。由于结构不同,我必须为每个新请求重新创建表。我相信问题 - 猴子的工作,但我无能为力,并提出更好的解决方案。谢谢。 – Arol

+0

全局临时表在Oracle中是情境性的:在很多情况下,它们并不是必需的,因为Oracle能够有效地运行相关的子查询。示例:不要执行3次插入temp并返回临时表,只需使用UNION ALL运行一个查询。如要进一步了解,对[askTom(http://asktom.oracle.com/pls/asktom/f?p=100:11:0::::P11_QUESTION_ID:15826034070548) –

相关问题