2012-10-24 118 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) –

相關問題