问题描述
如何将字符串参数传递给 EXTRACTVALUE
?
例如:
EXTRACTVALUE(fooColumn,'/foo/bar[@baz = "arg"]/@value')
如何用实参 "arg"
替换 :arg
?
简单的解决方案:
EXTRACTVALUE(fooColumn,'/foo/bar[@baz = "' || :arg || '"]/@value')
这里如何防止可能的“XPath”注入? 是否有 XPath 转义函数?
解决方法
EXTRACTVALUE
已弃用,您应该改用 XMLQUERY
或 XMLTABLE
。
您可以尝试使用 DBMS_ASSERT
包:
CREATE FUNCTION enquote_name (
name IN VARCHAR2
) RETURN VARCHAR2
IS
BEGIN
-- Wrap it in a function call to use the PL/SQL FALSE literal.
RETURN DBMS_ASSERT.ENQUOTE_NAME(name,FALSE);
END;
/
那么:
SELECT XMLQUERY(
('/foo/bar[@baz='||ENQUOTE_NAME(:arg)||']/@value')
PASSING fooColumn
RETURNING CONTENT
) AS value
FROM table_name
或
SELECT EXTRACTVALUE( foocolumn,'/foo/bar[@baz='||ENQUOTE_NAME(:arg)||']/@value')
AS value
FROM table_name
表:
CREATE TABLE table_name ( foocolumn ) AS
SELECT XMLTYPE(
'<foo><bar baz="abc" value="123" /><bar baz="def" value="456" /></foo>'
)
FROM DUAL;
输出,当 :arg
为 def
时:
VALUE |
---|
456 |
如果您尝试将 :arg
用作 'abc"][@value="123'
,则查询返回零行(或引发 EXTRACTVALUE
的异常);但是,如果您尝试传递相同的值而不将其包装在对 ENQUOTE_NAME
的调用中(并包括 ENQUOTE_NAME
将添加的双引号),那么它将执行您试图避免的 XPATH 注入。
dbfiddle here