创建表并从sql调用它

时间:2012-10-24 10:22:47

标签: sql plsql

我有一个PL / SQL函数,可以创建一个新的临时表。为了创建表,我使用execute immediate。当我在oracle 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;

2 个答案:

答案 0 :(得分:2)

错误是明确的:

  

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

在Oracle中,您无法在查询中提交。一个可能的解释是它没有意义,因为Oracle中的查询是原子的(要么完全成功要么不做任何改变),如果你在DML中提交,这就无法工作。对于select查询,必须从单个逻辑时间点返回所有行,如果在select中间提交,则会产生不一致的结果。

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

这在您的情况下应该不是问题:类似SQL服务器的临时表不等同于Oracle中的 GLOBALLY 临时表。 Oracle中的临时表始终以GLOBALLY为前缀是有原因的:尽管临时表中的数据对每个会话都是私有的,但它们对所有会话都是可见的。

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

在任何情况下,如果您决定执行多个依赖于SELECT的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;

答案 1 :(得分: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;