2015-08-20 47 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

相关问题