2015-08-20 94 views
9

下面的PL/SQL塊中的第一個和第二個「put_line」語句會成功,但最後一個失敗。爲什麼?它可能是一個錯誤?爲什麼最後的PL/SQL語句使用dbms_assert.enquote_literal失敗?

declare 
    x varchar2(100); 
begin 
    x := 'Test'''; 
    dbms_output.put_line('x is: ' || x || ', enquoted x is: ' || dbms_assert.enquote_literal(replace(x, '''', ''''''))); 

    x := 'Te''st'; 
    dbms_output.put_line('x is: ' || x || ', enquoted x is: ' || dbms_assert.enquote_literal(replace(x, '''', ''''''))); 

    x := '''Test'; 
    dbms_output.put_line('x is: ' || x || ', enquoted x is: ' || dbms_assert.enquote_literal(replace(x, '''', ''''''))); 
end; 
/

的錯誤是:

Error report: 
ORA-06502: PL/SQL: numeric or value error 
ORA-06512: at "SYS.DBMS_ASSERT", line 317 
ORA-06512: at "SYS.DBMS_ASSERT", line 381 
ORA-06512: at line 11 
06502. 00000 - "PL/SQL: numeric or value error%s" 
*Cause:  
*Action: 

任何想法?

+0

因爲它似乎與變量中的第一個字符有關。如果第一個字符是'',則拋出它。 – SomeJavaGuy

+0

查看dbms_assert的源代碼。 –

+0

感覺像馬車行爲。 – sstan

回答

1

不能告訴你爲什麼會這樣,但你可以嘗試如下處理這樣的:

set serveroutput on; 
declare 
    x varchar2(100); 
begin 
    x := 'Test'''; 
    dbms_output.put_line('x is: ' || x || ', enquoted x is: ' || replace(dbms_assert.enquote_literal(replace(x, '''', '''''')), ''' ', '''')); 

    x := 'Te''st'; 
    dbms_output.put_line('x is: ' || x || ', enquoted x is: ' || replace(dbms_assert.enquote_literal(replace(x, '''', '''''')), ''' ', '''')); 

    x := '''Test'; 

    dbms_output.put_line('x is: ' || x || ', enquoted x is: ' 
    || replace(dbms_assert.enquote_literal(replace(x, '''', ' ''''')), ''' ', '''') 
); 
end; 
/

x is: Test', enquoted x is: 'Test''' 
x is: Te'st, enquoted x is: 'Te''st' 
x is: 'Test, enquoted x is: '''Test' 
PL/SQL procedure successfully completed. 
+0

或者您可以嘗試以下方法:x:='''測試'; ('x':'|| x ||',引用的x是:' || replace(dbms_assert.enquote_literal(replace(x,'''','''''')), '''','''') ); –

+0

在回答中使用您的代碼並使用x:='''Test'後,仍然收到相同的錯誤。 –

+0

我剛剛編輯了答案,再次運行該plsql塊,然後檢查,我沒有收到任何錯誤。 –

1

它是在 https://avoidsqlinjection.wordpress.com/category/5-filtering-input-with-dbms_assert/When using ENQUOTE_LITERAL, remember to escape single quotes in the input.提及,但沒有很好的解釋。

在Oracle文檔http://docs.oracle.com/cd/E11882_01/appdev.112/e40758/d_assert.htm#ARPLS65379

Usage Notes  
     Verify that all single quotes except leading and trailing characters are paired with adjacent single quotes.  
     No additional quotes are added if the name was already in quotes. 

這個問題是很好的例子ENQUOTE_LITERAL不會qoute字符串這是上面已經不僅限制我們ENQUOTE_LITERAL.So什麼是這個方案中提到quoted.But什麼。正如@Vinish Kapoor在他的答案中所做的一樣,你可以看到。所以在有限制的情況下,我們可以將字符串轉換爲其他模式並將其替換回正常狀態。您可以使用下面也

dbms_output.put_line('x is: ' || x || ', enquoted x is: ' || replace(dbms_assert.enquote_literal(replace(x, '''', '#')), '#', '''')); 

或這一個

dbms_output.put_line('x is: ' || x || ', enquoted x is: ' || replace(dbms_assert.enquote_literal(replace(x, '''', '~')), '~', '''')); 

怎麼一回事,因爲開頭和結尾的單qoutes是造成問題,我們可以CONVER他們入#或〜和enquote_literal完成工作後,我們就可以取代它們回到單個qoutes。

+0

如果字符串已經包含#或〜字符,該怎麼辦? – RGO

相關問題