2015-02-10 195 views
0

請有人幫助一個很新手的Oracle人。我在Oracle中創建了一個存儲過程來刪除日期範圍分區。我用來創建程序的代碼是:Oracle sql存儲過程數據參數丟失單引號

SQL> CREATE OR REPLACE PROCEDURE NEW_EVENT_DELETE(palterdate in VARCHAR2) AS 
    2 begin 
    3 execute immediate 'ALTER TABLE ROSUSER.EVENT DROP PARTITION FOR(TO_DATE(palterdate, ''DD-MON-YYYY'')) UPDATE INDEXES'; 
    4 end NEW_EVENT_DELETE; 
    5/

編譯沒有問題,但是當我嘗試使用運行程序:

ERROR at line 1: 
ORA-14755: Invalid partition specification for FOR VALUES clause. 
ORA-06512: at "ROSUSER.NEW_EVENT_DELETE", line 3 
ORA-06512: at line 1 

exec NEW_EVENT_DELETE('03-FEB-2014'); 

它回來如果我使用命令:

ALTER TABLE ROSUSER.EVENT DROP PARTITION FOR(TO_DATE('03-FEB-2014', 'DD-MON-YYYY')); 

然後它工作。在我看來,輸入日期周圍的單引號集正在丟失,因爲如果我試圖在日期周圍沒有引號的情況下運行ALTER命令,那麼它就是我得到的同樣的錯誤消息。

任何想法我做錯了什麼?

感謝您的任何幫助

+0

嘗試NEW_EVENT_DELETE(「03-FEB-2014」);而不是單個'' – Unlockedluca 2015-02-10 15:37:50

+1

@Unlockedluca:Oracle不會使用這樣的雙引號。單引號是正確的。 – Ditto 2015-02-10 15:40:29

回答

0

如果你把這樣的引號?

1 CREATE OR REPLACE PROCEDURE NEW_EVENT_DELETE(palterdate in VARCHAR2) AS 
2 begin 
3 execute immediate 'ALTER TABLE ROSUSER.EVENT DROP PARTITION FOR(TO_DATE('''||palterdate||''', ''DD-MON-YYYY'')) UPDATE INDEXES'; 
4 end NEW_EVENT_DELETE; 
5/

解釋:爲什麼3個引號?一個逃避另一個和最後一個串聯

編輯:對不起,我用'+'連接,因爲我認爲它是在SQl服務器上,你必須使用'||'運營商

+1

謝謝,所有。使用'''|| palterdate ||''',它的工作非常出色!再次感謝 – 2015-02-11 16:22:29

1

您沒有正確傳遞palterdate在立即執行。將其更改爲:

execute immediate 'ALTER TABLE ROSUSER.EVENT DROP PARTITION FOR(TO_DATE('''||palterdate||''', ''DD-MON-YYYY'')) UPDATE INDEXES' 

儘管您需要考慮有關sql注入的問題,因爲此代碼可能會被劫持。

+0

回覆:sql注入 - 這隻取決於傳入日期的來源。如果它是在某個計劃的批處理例程中計算的,那麼sql注入極不可能是一個問題(即沒有用戶輸入)。但是,是的,任何時候如果你用動態sql搞砸了,你必須給出一些想法。 ;)(因此,如果可能的話,避免動態sql) – Ditto 2015-02-10 15:52:42

2

當報價行情打交道,我一直喜歡這種格式:

execute immediate q'[ALTER TABLE ROSUSER.EVENT DROP PARTITION FOR(TO_DATE(']' || palterdate || q'[', 'DD-MON-YYYY')) UPDATE INDEXES]'; 

甚至:

lv_sql := q'[ALTER TABLE ROSUSER.EVENT DROP PARTITION FOR(TO_DATE('<palterdate>', 'DD-MON-YYYY')) UPDATE INDEXES]'; 
    lv_sql := REPLACE(lv_sql, '<palterdate>', palterdate); 
    execute immediate lv_sql; 
1

或者,看看使用選項執行即時

execute immediate 'ALTER TABLE ROSUSER.EVENT DROP PARTITION FOR(TO_DATE(:palterdate, ''DD-MON-YYYY'')) UPDATE INDEXES' USING palterdate; 

而且,對於SQL注入問題,快速檢查palterdate可能會解決大多數問題。很難在11個字符中嵌入額外的語句! ;)