pl/sql - Using a dynamic query inside a stored procedure
I am using a stored procedure to insert data into a temp table using a cursor. This procedure stores a dynamic query inside a variable to mount the insert/update command.
Here is the code(not the full query, I've cut some parts to make it easier to read):
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 TERRIT开发者_StackOverflow中文版ORIO = ''' || VC2.NOME || '''
AND PRODUTO = ''' || VC2.PRODUTO || ''';'
INTO V_SQL FROM DUAL;
EXECUTE IMMEDIATE (V_SQL);
END LOOP
Inside the dynamic query, in this part "SET TARGET = ' || VC2.OBJETIVO || '"
the value VC2.OBJETIVO
is a Number
type, and it's replaced like "62481,76". In other words, this comma is making the command wrong and doesn't work.
Is there an easy way to replace the "," for "."?
Thank you very much! (:
Don't build your query by appending strings. You leave yourself open to lots of bugs and vulnerabilities, first of all SQL injection. The need to use dynamic queries doesn't justify not using bind variables. If you really need to use dynamic queries (it is not clear from your example why static update wouldn't work?!), do this instead:
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 will correctly bind with the appropriate type.
I don't see any need to use dynamic SQL at all.
Why not something like:
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;
I am using Oracle 11g , last couple of day I was facing problem of execute dynamic query in oracle procedure. I did search lots off. finally i have got solution .
-- 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;
精彩评论