2014-05-12 67 views
0

我試圖將一個預定義的Oracle數據庫管理用戶帳戶存儲到一個表DBOMIT_SCHEMAS使用列表schema_list在代碼中。在EXECUTE IMMEDIATE中使用SQL時如何解決ORA-00984?

DECLARE 
    TYPE schema_list_type IS TABLE OF "DBCONTROL"."DBSCHEMA_INFO".SCHEMA%TYPE; 
    schema_list schema_list_type; 
BEGIN 
    schema_list := schema_list_type('ANONYMOUS', 'CTXSYS', 'DBSNMP', 'EXFSYS', 'LBACSYS', 'MDSYS', 'MGMT_VIEW','OLAPSYS', 'OWBSYS', 'ORDPLUGINS', 'ORDSYS', 'OUTLN', 'SI_INFORMTN_SCHEMA', 'SYS', 'SYSMAN', 'SYSTEM', 'TSMSYS', 'WK_TEST', 'WKSYS', 'WKPROXY', 'WMSYS', 'XDB'); 

    FOR i IN schema_list.FIRST .. schema_list.LAST 
    LOOP 
    DBMS_OUTPUT.PUT_LINE('***DEBUG***: '||schema_list(i)); 
    EXECUTE IMMEDIATE('INSERT INTO "DBCONTROL"."DBOMIT_SCHEMAS" VALUES('||schema_list(i)||')'); 
    END LOOP; 

END; 

當我通過列表嘗試循環和每個值插入表中,我得到ORA-00984:這裏錯誤不允許列。我想,發生這種情況是因爲它理解ANONYMOUS(列名)而不是'ANONYMOUS'(字符串)。誰能解決這個問題嗎?

回答

2

kodiko是正確的,你不需要動態SQL在這裏的所有,而不應使用它來(因爲沒有必要 - 難寫,難以調試......)。但是對於你的實際錯誤,這是因爲你使用了一個硬編碼的字符串值而沒有用引號括起來。您可能需要使用:

EXECUTE IMMEDIATE('INSERT INTO "DBCONTROL"."DBOMIT_SCHEMAS" VALUES(''' 
    ||schema_list(i)||''')'); 

這改變了執行的SQL從VALUES(ANONYMOUS)VALUES('ANONYMOUS')結束。額外的引號翻倍,因爲它們需要被轉義,這就是機制。 (你可以使用另外的引用語法,但是當我建立一個字符串時,我發現它不那麼明顯有用)。

但你不應該硬編碼的價值可言,你應該使用綁定變量:

EXECUTE IMMEDIATE('INSERT INTO "DBCONTROL"."DBOMIT_SCHEMAS" VALUES(:id)') 
USING schema_list(i); 

那麼,在這種情況下,你應該使用簡單的SQL,但如果這樣做必須使用動態SQL,那麼你應該使用綁定變量。

我也會丟失模式和表名稱的雙引號,因爲它們不需要引用,所以它們實際上只是噪聲。你也可以用forall做批量插入,如果type是在模式級別聲明的,那麼你可以在沒有循環的情況下在一個插入中做到這一點,但我想這是一個練習。

+0

當我使用純SQL語句時,我得到** ORA-06550:**錯誤。這是因爲我有一個** EXECUTE IMMEDIATE **語句來在插入值之前創建表。我嘗試將它們分開,並且它工作正常。即使當我使用綁定變量,我得到** ORA-00911:無效字符**錯誤。它可以根據需要使用額外的引號。 – Syam

+1

@Syam - 是的,如果你是動態創建表,你是對的,插入也必須是動態的。 (即時創建表非常不尋常)。你不需要綁定變量的引號;但如果我使用Oracle':var'語法而不是JDBC'''語法,它確實會有所幫助。如果你只是把引號括起來,那麼表中插入的所有值都將是''?'',而不是實際的模式名稱。我已經糾正(並測試)了,對不起。 –

2

你不需要在這裏進行即時的,只是做:

LOOP 
    DBMS_OUTPUT.PUT_LINE('***DEBUG***: '||schema_list(i)); 
    INSERT INTO "DBCONTROL"."DBOMIT_SCHEMAS" VALUES(schema_list(i)); 
    END LOOP; 
相關問題