create or replace
PROCEDURE TEST3(CREATED_BY_IN IN VARCHAR2,SRC_NAME IN VARCHAR2,TGT_NAME IN VARCHAR2,OUTPUT OUT VARCHAR2)
IS
CHECK_STATUS INTEGER;
SRCSQL VARCHAR(1000);
BEGIN
SRCSQL:= 'INSERT INTO TBLCNT SELECT '||''''||CREATED_BY_IN||''''||','|| ' COUNT(*),' ||''''||SRC_NAME||''''||' FROM '||SRC_NAME ;
EXECUTE IMMEDIATE SRCSQL USING CREATED_BY_IN,SRC_NAME;
OUTPUT:=SRCSQL;
END;
Iam getting the error stating 'Bind variable does not exist'.
Can anyone please help me with this
You are performing a query with concatenated text and variable, so you can't use execute immediate with binded variables since they are not used in this case.
the right syntaxe is :
SRCSQL:= 'INSERT INTO TBLCNT SELECT :p1, COUNT(*), :p2 FROM :p2';
EXECUTE IMMEDIATE SRCSQL USING CREATED_BY_IN, SRC_NAME, SRC_NAME;
See documentation https://docs.oracle.com/cd/B13789_01/appdev.101/b10807/13_elems017.htm
You can use this without the help of bind variables. Hope below snippet helps .
CREATE OR REPLACE PROCEDURE TEST3(
CREATED_BY_IN IN VARCHAR2,
SRC_NAME IN VARCHAR2,
TGT_NAME IN VARCHAR2,
OUTPUT OUT VARCHAR2)
IS
CHECK_STATUS INTEGER;
SRCSQL VARCHAR(1000);
BEGIN
SRCSQL:= 'INSERT INTO TBLCNT SELECT '||''''||CREATED_BY_IN||''''||','|| ' COUNT(*),' ||''''||SRC_NAME||''''||' FROM '||SRC_NAME ;
EXECUTE IMMEDIATE SRCSQL;
OUTPUT:=SRCSQL;
END;
Related
create sequence s1 ;
declare
v_value number;
v_sql_stmt varchar2(4000);
v_seq_name varchar2(30);
BEGIN
v_seq_name:='S1'; -- **this is dynamic and the sequence will be passed in the proc as input parameter at runtime**
v_sql_stmt:= 'select :v_seq_name'||'.nextval from dual' ;
EXECUTE IMMEDIATE v_sql_stmt INTO v_value USING v_seq_name ;
--**below is working but I dont want to do in this way because of sql injection issue, let me know how to fix the above**
--EXECUTE IMMEDIATE 'select ' || v_seq_name || '.nextval from dual' INTO v_value;
dbms_output.put_line(v_value);
end;
/
the above code is throwing error, please help to fix.
If you run the commented code then it will run but I dont want to use || in execute immediate. I want to use colon : only.
the sequence name will be passed at run time. The above code will be converted to a proc later.
I understand your concern about SQL injection. To my knowledge, table/column/sequence names cannot be specified with bind variables. However, you could do a simple check before executing the unsafe code:
CREATE SEQUENCE s1;
CREATE SEQUENCE s2;
CREATE OR REPLACE FUNCTION p(seq_name VARCHAR2) RETURN NUMBER AS
v_value number;
v_sql_stmt varchar2(4000);
v_seq_name varchar2(128 BYTE);
BEGIN
v_seq_name:= DBMS_ASSERT.SIMPLE_SQL_NAME(seq_name);
v_sql_stmt:= 'select '||v_seq_name||'.nextval from dual';
EXECUTE IMMEDIATE v_sql_stmt INTO v_value;
RETURN v_value;
END p;
/
If a valid name is used, everything works as expected:
select p('s1') from dual;
1
select p('s2') from dual;
2
However, if seq_name is not a valid Oracle name, DBMS_ASSERT throws an exception:
select p('1; DROP TABLE x') from dual;
ORA-44003: invalid SQL name
ORA-06512: at "SYS.DBMS_ASSERT", line 215
ORA-06512: at "WFL.P", line 6
44003. 0000 - "invalid SQL name"
I am making a procedure but I am getting a error(PLS-00382: expression is of wrong type) while executing statement in the line(EXECUTE IMMEDIATE V_QUERY)`:
CREATE OR REPLACE PROCEDURE SUMMARY(V_NDAY IN NUMBER ) IS
V_QUERY NVARCHAR2 (5000);
BEGIN
V_QUERY := 'DROP TABLE temp_summary';
EXECUTE IMMEDIATE V_QUERY;
END SUMMARY;
Try changing the data type from 'V_QUERY' to VARCHAR2 and not NVARCHAR2.
Use VARCHAR2 instead of NVARCHAR2. This will solve the problem.
Here's my stored procedure:
CREATE OR REPLACE PROCEDURE STATS_SD
(
P_ID IN NUMBER,
PRC OUT SYS_REFCURSOR
)
IS
BEGIN
OPEN PRC FOR
SELECT
ID,
SESID
FROM RESPONSES
WHERE ID IN (P_ID)
END;
When I try to execute it using
EXEC EXAM_STATS_STUDENTS_SD('6901');
I get the following error:
PLS-00306: wrong number or types of arguments in call to 'STATS_SD'
Do you have any ideas why?
Here is an example using an OUT parameter that is a sys_refcursor. Note that I close the cursor in the pl/sql block that uses it (which is important!):
create or replace procedure get_data(o_cur OUT SYS_REFCURSOR) as
begin
OPEN o_cur FOR
select * from emp;
end;
And using the get_data procedure:
declare
l_cur sys_refcursor;
l_row emp%rowtype;
begin
get_data(l_cur);
LOOP
fetch l_cur
into l_row;
exit when l_cur%notfound;
-- do something with l_row here
END LOOP;
close l_cur;
end;
You are passing a wrong datatype to your procedure.
According to your declaration a NUMBER is expected:
P_ID IN NUMBER
However, you pass a VARCHAR2 in your exec command:
EXEC EXAM_STATS_STUDENTS_SD('6901');
Note the '' around the value.
Try calling this instead:
EXEC EXAM_STATS_STUDENTS_SD(6901);
Apart from that you are missing the second parameter completely.
I am trying to execute the below plsql program, but facing expression of wrong type. Could anyone let me know what might be the error?
CREATE OR REPLACE PROCEDURE CLN_TBL (CTRLM IN VARCHAR2, CTG IN VARCHAR,SBCT IN NUMBER, RTDT IN NUMBER )
AS
V_SQL VARCHAR(2000);
V_TABLE VARCHAR(30);
CURSOR TBL_CUR
IS
SELECT TGT_TABLE_NAME FROM ODS_USER.CLNP WHERE CONTROLM=CTRLM AND APPL_CTGY=CTG AND APPL_SUB_CTGY= SBCT;
L_TGT_TABLE_NAME TBL_CUR%ROWTYPE;
BEGIN
OPEN TBL_CUR;
LOOP
FETCH TBL_CUR INTO L_TGT_TABLE_NAME;
V_TABLE:= L_TGT_TABLE_NAME ;
EXIT WHEN TBL_CUR%NOTFOUND;
V_SQL:='DELETE FROM '||V_TABLE||' WHERE RPT_DT_ID'||'=:1';
EXECUTE IMMEDIATE V_SQL using RTDT;
END LOOP;
COMMIT;
CLOSE TBL_CUR;
END;
As Exhausted said you cant assign row variable to varchar so You should take TGT_TABLE_NAME from row variable, like below should work;
CREATE OR REPLACE PROCEDURE CLN_TBL (CTRLM IN VARCHAR2, CTG IN VARCHAR,SBCT IN NUMBER, RTDT IN NUMBER )
AS
V_SQL VARCHAR(2000);
V_TABLE VARCHAR(30);
CURSOR TBL_CUR
IS
SELECT TGT_TABLE_NAME FROM ODS_USER.CLNP WHERE CONTROLM=CTRLM AND APPL_CTGY=CTG AND APPL_SUB_CTGY= SBCT;
L_TGT_TABLE_NAME TBL_CUR%ROWTYPE;
BEGIN
OPEN TBL_CUR;
LOOP
FETCH TBL_CUR INTO L_TGT_TABLE_NAME;
V_TABLE:= L_TGT_TABLE_NAME.TGT_TABLE_NAME ;
EXIT WHEN TBL_CUR%NOTFOUND;
V_SQL:='DELETE FROM '||V_TABLE||' WHERE RPT_DT_ID'||'=:1';
EXECUTE IMMEDIATE V_SQL using RTDT;
END LOOP;
COMMIT;
CLOSE TBL_CUR;
END;
So I'm writing a stored procedure and am having trouble getting the next value of a sequence into a variable.
The sequence name is passed into the function and is stored as a varchar2 variable. How can you get the next value in that sequence into a local variable.
Something like this?
create or replace procedure next_val (p_sequence_name varchar2)
as
v_nextval integer;
v_select varchar2(100);
begin
v_select := 'select '||p_sequence_name||'.nextval from dual';
execute immediate v_select into v_nextval;
dbms_output.put_line('Nextval is: '||TO_CHAR(v_nextval));
end;