我正在使用存储过程使用游标将数据插入临时表。 此过程在变量中存储动态查询以装入insert / update命令。
这是代码(不是完整的查询,我已经剪切了一些部分以便于阅读):
FOR VC2 IN (SELECT C.OBJETIVO,
C.AUDITORIA ,
C.NOME,
C.PRODUTO
FROM CALCULO C)
LOOP
SELECT ' V_UPD NUMBER := 0;
SELECT (SELECT ID_TIPO_TERR
FROM ZREPORTYTD_TMP
WHERE AUDITORIA = ''' || VC2.AUDITORIA || '''
AND TERRITORIO = ''' || VC2.NOME || '''
AND PRODUTO = ''' || VC2.PRODUTO || ''')
INTO V_UPD FROM DUAL;
UPDATE ZReportYTD_TMP
SET TARGET = ' || VC2.OBJETIVO || '
WHERE AUDITORIA = ''' || VC2.AUDITORIA || '''
AND TERRITORIO = ''' || VC2.NOME || '''
AND PRODUTO = ''' || VC2.PRODUTO || ''';'
INTO V_SQL FROM DUAL;
EXECUTE IMMEDIATE (V_SQL);
END LOOP
在动态查询中,在此部分"SET TARGET = ' || VC2.OBJETIVO || '"
中,值VC2.OBJETIVO
是Number
类型,并且它被替换为“62481,76”。换句话说,这个逗号使命令错误并且不起作用。
是否有一种简单的方法可以替换“。”?“
非常感谢! (:
答案 0 :(得分:15)
不要通过附加字符串来构建查询。首先,SQL注入会给你留下许多漏洞和漏洞。使用动态查询的需要并不能证明不使用绑定变量。如果你真的需要使用动态查询(从你的例子中不清楚为什么静态更新不起作用?!),请改为:
FOR vc2 IN (...) LOOP
v_sql :=
'BEGIN
V_UPD NUMBER := 0;
SELECT (SELECT ID_TIPO_TERR
FROM ZREPORTYTD_TMP
WHERE AUDITORIA = :p1
AND TERRITORIO = :p2
AND PRODUTO = :p3)
INTO V_UPD FROM DUAL;
UPDATE ZReportYTD_TMP
SET TARGET = :p4
WHERE AUDITORIA = :p5
AND TERRITORIO = :p6
AND PRODUTO = :p7;
END';
EXECUTE IMMEDIATE v_sql USING VC2.AUDITORIA, VC2.NOME, VC2.PRODUTO,
VC2.OBJETIVO, VC2.AUDITORIA, VC2.NOME,
VC2.PRODUTO;
END LOOP;
Oracle将使用适当的类型正确绑定。
答案 1 :(得分:1)
我认为根本不需要使用动态SQL。
为什么不能这样:
FOR VC2 IN (SELECT C.OBJETIVO,
C.AUDITORIA ,
C.NOME,
C.PRODUTO
FROM CALCULO C) LOOP
v_upd := 0;
SELECT
ID_TIPO_TERR
into
v_UPD
FROM
ZREPORTYTD_TMP
WHERE
AUDITORIA = VC2.AUDITORIA
AND TERRITORIO = VC2.NOME
AND PRODUTO = VC2.PRODUTO;
-- is v_upd used anywhere?
UPDATE
ZReportYTD_TMP
SET
TARGET = VC2.OBJETIVO
WHERE
AUDITORIA = VC2.AUDITORIA
AND TERRITORIO = VC2.NOME
AND PRODUTO = VC2.PRODUTO;
END LOOP;
答案 2 :(得分:0)
我正在使用Oracle 11g,过去几天我遇到了问题 在oracle过程中执行动态查询。我做了很多搜索。 最后我得到了解决方案。
-- In blow procedure we pass multiple argument at run time
-- We need reference cursor for dynamic query execution
create or replace PROCEDURE FETCH_REPORT1_NEW(IPID IN number ,CAID IN number,
ZOID IN number,CLID IN number,SDATE VARCHAR2 , EDATE
VARCHAR2,OUT_VALUE OUT VARCHAR2)
IS
l_sql varchar(200); TYPE cursor_ref IS REF CURSOR; c1
cursor_ref;
UZID transaction_data.zone_id%TYPE; OUTAGE_MINS
transaction_data.durationmin%TYPE;
BEGIN
l_sql := 'select Avg (durationmin) , zone_id ,
from transaction_data where alarm_id in (1,21,26,20) and zone_id not in(5)';
IF IPID>0 THEN
l_sql := l_sql||' and IP_ID = '||IPID;
END IF;
l_sql := l_sql||' group by (zone_id)';
open c1 for l_sql;
loop
fetch c1 into OUTAGE_MINS,UZID;
dbms_output.put_line(OUTAGE_MINS||UZID);
exit when c1%notfound;
end loop;
close c1;
END;