我創建了一個函式,它使用動態 sql:
create function check_ref_value
(
table_name varchar2,
code_value number,
code_name varchar2
) return number is
l_query varchar2(32000 char);
l_res number;
begin
l_query := '
select sign(count(1))
into :l_res
from '|| table_name ||'
where '|| code_name ||' = :code_value
';
execute immediate l_query
using in code_value, out l_res;
return l_res;
end;
但是當我嘗試使用它時,出現例外“ORA-00933:SQL 命令未正確結束”這段代碼有什么問題?
uj5u.com熱心網友回復:
您可以使用EXECUTE IMMEDIATE ... INTO ... USING ...獲取回傳值并DBMS_ASSERT在 SQL 注入嘗試的情況下引發錯誤:
create function check_ref_value
(
table_name varchar2,
code_value number,
code_name varchar2
) return number is
l_query varchar2(32000 char);
l_res number;
begin
l_query := 'select sign(count(1))'
|| ' from ' || DBMS_ASSERT.SIMPLE_SQL_NAME(table_name)
|| ' where ' || DBMS_ASSERT.SIMPLE_SQL_NAME(code_name)
|| ' = :code_value';
execute immediate l_query INTO l_res USING code_value;
return l_res;
end;
/
其中,對于樣本資料:
CREATE TABLE abc (a, b, c) AS
SELECT 1, 42, 3.14159 FROM DUAL;
然后:
SELECT CHECK_REF_VALUE('abc', 42, 'b') AS chk FROM DUAL;
輸出:
CHK 1
和:
SELECT CHECK_REF_VALUE('abc', 42, '1 = 1 OR b') AS chk FROM DUAL;
引發例外:
ORA-44003: invalid SQL name ORA-06512: at "SYS.DBMS_ASSERT", line 160 ORA-06512: at "FIDDLE_UVOFONEFDEHGDQJELQJL.CHECK_REF_VALUE", line 10
至于你的問題:
這段代碼有什么問題?
UsingSELECT ... INTO僅在 PL/SQL 塊中的 SQL 陳述句中有效,并且當您通過EXECUTE IMMEDIATE它運行該陳述句時,它會在 SQL 范圍內執行,而不是在 PL/SQL 范圍內執行。
您可以通過將動態代碼包裝在BEGIN .. ENDPL/SQL 匿名塊中(并顛倒USING子句中系結引數的順序)來修復它:
create function check_ref_value
(
table_name varchar2,
code_value number,
code_name varchar2
) return number is
l_query varchar2(32000 char);
l_res number;
begin
l_query := '
BEGIN
select sign(count(1))
into :l_res
from '|| DBMS_ASSERT.SIMPLE_SQL_NAME(table_name) ||'
where '|| DBMS_ASSERT.SIMPLE_SQL_NAME(code_name) ||' = :code_value;
END;
';
execute immediate l_query
using out l_res, in code_value;
return l_res;
end;
/
(但是,這是一個更復雜的解決方案,僅使用EXECUTE IMMEDIATE ... INTO ... USING ....)
db<>在這里擺弄
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/373102.html
