2015-04-21 16 views
0

我有我需要刪除和創建表的功能。在下面的例子中我嘗試創建表,但它無法如何在Oracle函數內創建和刪除表?

CREATE OR REPLACE FUNCTION DEVTEST 
RETURN NUMBER 
IS 
    COMMAND VARCHAR2(256); 
    ID   VARCHAR2(128); 
    NAME  VARCHAR2(128); 
    TMP_LIST VARCHAR2(128); 
BEGIN 
    ID := '12345'; 
    NAME := 'ABCdef'; 
    TMP_LIST := 'tmpTest'; 

    command := 'create table ' || TMP_LIST || ' (USER_ID VARCHAR2(11), USER_NAME VARCHAR2(36))'; 
    DBMS_OUTPUT.PUT_LINE('command = ' || command); 
    EXECUTE IMMEDIATE command; 
return 0; 
END; 

我調用該函數:

select NSB_DEVTEST() from dual 

並且得到錯誤:

ORA-14552:無法執行DDL,在查詢或DML中提交或回滾ORA-06512:在「DEV1_SERVER.DEVTEST」,第15行

如何更正此問題以在函數內創建/刪除表?

我的服務器的詳細信息:

  • Oracle數據庫10g企業版發佈10.2.0.5.0 - 64bi
  • PL/SQL發佈10.2.0.5.0 - 生產
  • CORE 10.2.0.5.0生產
  • TNS用於Solaris:版本10.2.0.5.0 - 生產
  • NLSRTL版10.2.0.5.0 - 生產
+0

爲什麼一個函數而不是一個過程? – Mat

+0

這並不回答你的問題,但動態創建/刪除表幾乎總是錯誤的方法。你需要一個'TEMPORARY TABLE'嗎? –

+0

使用過程,而不是函數 –

回答

2

你的問題的答案是:不。整體而言,生產代碼不應該即時創建表格。如果您需要一張表來臨時保存數據,則創建一次全局臨時表(GTT)並讓您的代碼參考它。

你得到這個錯誤的原因(除了它從錯誤信息中不言而喻)是因爲你從一個SQL語句中調用函數。你不能那樣做;你必須直接在PL/SQL中調用它。

我很好奇你爲什麼認爲這種方法是一種很好的,可行的方法,以及一旦你創建了它,你將如何處理這個表。

2

問題不在函數中,而是從SQL語句而不是從pl/sql塊中調用。

SQL中的SELECT語句等同於讀取一致性的READ操作。它不能對數據庫進行任何更改。在「READ」操作完成之前和之後,數據庫應該始終保持相同,否則它將成爲WRITE操作,整個數據庫一致性將受到嚴重破壞。另外,就像錯誤說的那樣,DDL操作在它們啓動之前在幕後執行COMMIT。任何讀取一致操作都不應執行任何COMMITS並在用戶不知情的情況下寫入數據庫。

你可以調用,而不是從功能PL/SQL這樣的 -

DECLARE 
l_result NUBMER; 
BEGIN 
l_result := DEVTEST; 
DBMS_OUTPUT.PUT_LINE(l_number); 
END; 

不過我寧願寫這個程序,讓別人不要被爲什麼不能從被稱爲混淆SQL。我遵循的一般原則是 - 函數「獲取」事物和過程「做」事物(如DML)。

+0

也聽@ @Boneist爲什麼你不應該在代碼中創建表。 – ruudvan

+0

有關數據庫純度規則的更多信息,請參閱sql語句中調用的函數:http://docs.oracle.com/cd/B19306_01/appdev.102/b14261/subprograms.htm#i22204 –