在Oracle中,DBMS_SQLHASH.GETHASH是返回查询哈希的好方法,而不是滚动自己的哈希代码。我们使用它已经有一段时间了,一切都很好,如下所示:
SELECT DBMS_SQLHASH.GETHASH(q'[SELECT * FROM SCOTT.EMP ORDER BY 1]', 1) FROM DUAL;
但是现在我们遇到了一些情况,我们需要将绑定变量传递到已执行的字符串中,而我无法找到这样做的方法。
实际上,我们正在努力做到这一点:
SELECT DBMS_SQLHASH.GETHASH(q'[SELECT * FROM SCOTT.EMP WHERE JOB = 'CLERK' ORDER BY 1]', 1) FROM DUAL;
这显然有效,但不使用绑定变量,而且有点难看。
我的想法是使用动态SQL绑定变量:
DECLARE
vResult VARCHAR2(4000);
vRole VARCHAR2(5) := 'CLERK';
BEGIN
EXECUTE IMMEDIATE
'SELECT DBMS_SQLHASH.GETHASH(''SELECT * FROM SCOTT.EMP WHERE JOB = :Role ORDER BY 1'', 1) FROM DUAL'
INTO vResult
USING vRole;
DBMS_OUTPUT.PUT_LINE(vResult);
END;
/
但这将返回ORA-01006:绑定变量不存在,这可能是因为执行立即字符串中的绑定变量也在字符串中。
我已经看到了一些建议,可能会使用DBMS_SQL以我想要的方式执行查询,但是我沿着这些思路进行的实验也得到了同样的结果。
是否有可能以这种方式传递绑定变量,还是我注定要在没有它们的情况下重写查询?
谢谢!
发布于 2018-12-28 08:34:51
在这种情况下,文字连接是正确的解决方案:
CREATE OR REPLACE PROCEDURE my_hash( p_job IN VARCHAR2 )
IS
vResult VARCHAR2( 4000 );
v_statement VARCHAR2( 500 )
:= q'[SELECT DBMS_SQLHASH.GETHASH('SELECT * FROM HR.EMPLOYEES WHERE JOB_ID = '']' || p_job || q'['' ORDER BY 1', 1) FROM DUAL]';
BEGIN
DBMS_OUTPUT.PUT_LINE( v_statement );
EXECUTE IMMEDIATE v_statement INTO vResult;
DBMS_OUTPUT.PUT_LINE( vResult );
END;
/
DECLARE
vRole VARCHAR2( 12 ) := 'PU_CLERK';
BEGIN
my_hash( vRole );
END;
/
我为人力资源计划重编了你的例子。注意,即使在q‘[]符号中,双引号也是必需的,因为有两级解析。这也阻止了SQL注入,因为参数将始终被解释为文本值。
https://stackoverflow.com/questions/50855597
复制相似问题