在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:绑定变量不存在,可能是因为execute immediate字符串中的绑定变量也在字符串内。
我已经看到一些建议,可能会使用 DBMS_SQL 以我想要的方式执行查询,但我沿着这些方面的实验导致了相同的结果。
是否有可能以这种方式传入绑定变量,或者我注定要在没有它们的情况下重新编写查询?
谢谢!
答案 0 :(得分:0)
在这种情况下,文字串联是正确的解决方案:
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注入,因为Parameter始终将被解释为文本值。