Dynamically resolve to reference cursor - oracle

I am trying to dynamically resolve the value from cursor something like below.
create or replace
PROCEDURE test(
PI_JANUS_ID IN VARCHAR2,
PO_dummy out Types.CursorType
)AS
PO_ACTUALCUROSR Types.CursorType;
cur_row tab%ROWTYPE;
val1 varchar2(100);
val2 varchar2(200);
BEGIN
open PO_ACTUALCUROSR for select * from tab;
LOOP
FETCH PO_ACTUALCUROSR into cur_row;
EXIT WHEN PO_ACTUALCUROSR%NOTFOUND;
val1 := 'TNAME';
SELECT 'cur_row.'||val1 INTO val2 FROM DUAL;
dbms_output.put_line('Column Value ' || val2);
END LOOP ;
CLOSE PO_ACTUALCUROSR;
END;
Here if you see I have to call cur_row. to get the value but here I have the column name in a variable (val1). So how will I take the value from the cursor.
If I execute the above block I would see "cur_row.TNAME" but I actually need the value in the cursor.
Is there a way of doing this.
Any help is very much appreciated.

just do
BEGIN
open PO_ACTUALCUROSR for select * from tab;
LOOP
FETCH PO_ACTUALCUROSR into cur_row;
EXIT WHEN PO_ACTUALCUROSR%NOTFOUND;
val2 := cur_row.tname;
dbms_output.put_line(val2);
END LOOP ;
CLOSE PO_ACTUALCUROSR;
end;
or
dbms_output.put_line(cur_row.tname);
directly will also work.
p.s. your variable
val2 varchar2(200);
is better as
val2 tab.tname%type;
if you're saying you need to dynamically pull columns without knowing the column name ahead of time you'd have to use dynamic sql, and as you're using a pl/sql array, we need to put that in a package spec so that we can reference it (as you cannot pass pl/sql only types into dynamic SQL).
SQL> create table tab(id number, col1 varchar2(10));
Table created.
SQL> insert into tab values (1, 'a');
1 row created.
SQL> commit;
Commit complete.
SQL> create package global_var
2 as
3 cur_row tab%rowtype;
4 end;
5 /
Package created.
SQL> declare
2 po_actualcurosr sys_refcursor;
3 val1 varchar2(10) := 'COL1';
4 val2 tab.col1%type;
5 begin
6 open po_actualcurosr for select * from tab;
7
8 loop
9 fetch po_actualcurosr into global_var.cur_row;
10 exit when po_actualcurosr%notfound;
11 execute immediate 'begin :a := global_var.cur_row.'||dbms_assert.simple_sql_name(val1)||'; end;' using out val2;
12 dbms_output.put_line(val2);
13 end loop ;
14 close po_actualcurosr;
15 end;
16 /
a
PL/SQL procedure successfully completed.

Related

How to execute Dynamic sql with insert statement in Oracle

Below sql command is not working in procedure
PROCEDURE P_EMPDETAIL
AS
V_WHERE := 'E.EMP_ID = 123'B
BEGIN
EXECUTE IMMEDIATE 'INSERT INTO EMPLOYEE E ' || V_WHERE || ;
END;
It seems to me there are various issues with your syntax and approach (you shouldn't be using dynamic SQL this way), perhaps you should learn PL/SQL and reference the manuals. The insert statement is also wrong. Below is the correct syntax.
CREATE OR REPLACE PROCEDURE P_EMPDETAIL as
V_WHERE varchar2(100);
BEGIN
V_WHERE := 'E.EMP_ID = 123';
EXECUTE IMMEDIATE 'INSERT INTO EMPLOYEE E (colname) values (1) ' || V_WHERE;
END;
Well, not exactly like that (obviously; otherwise, you wouldn't be asking for help).
It is unclear what you want to do because syntax is really strange. If you wanted to insert a row into the table, then:
SQL> CREATE TABLE employees
2 (
3 emp_id NUMBER
4 );
Table created.
SQL> CREATE OR REPLACE PROCEDURE p_empdetail (par_emp_id IN NUMBER)
2 AS
3 l_str VARCHAR2 (200);
4 BEGIN
5 l_str := 'insert into employees (emp_id) values (:1)';
6
7 EXECUTE IMMEDIATE l_str
8 USING par_emp_id;
9 END;
10 /
Procedure created.
Testing:
SQL> EXEC p_empdetail(123);
PL/SQL procedure successfully completed.
SQL> SELECT * FROM employees;
EMP_ID
----------
123
SQL>

Pass PL/SQL parameter as SCHEMA NAME

I'm trying to send variable schema name to cursor via procedure input
Here is my lame try, but you can see what I want to do:
CREATE OR REPLACE PROCEDURE HOUSEKEEPING
(SCHEMANAME in varchar2)
IS
CURSOR data_instances IS select table_name
from SCHEMANAME.table_name where TYPE='PERMANENT' and rownum<200 ;
BEGIN
DBMS_OUTPUT.PUT_LINE(SCHEMANAME);
END;
/
it throws expected
PL/SQL: ORA-00942: table or view does not exist
is there lawful way to make schema name work as variable? thanks
There is a way; you'll need some kind of dynamic SQL because you can't use schema (or object) names like that. For example, you could use refcursor instead.
Sample table:
SQL> create table table_name as
2 select 'EMP' table_name, 'PERMANENT' type from dual union all
3 select 'DEPT' , 'TEMPORARY' from dual union all
4 select 'BONUS' , 'PERMANENT' from dual;
Table created.
Procedure; note the way I composed SELECT statement first (so that I could display it and check whether it is correct), and then used it in OPEN. Loop is here to ... well, loop through the cursor. I'm just displaying table names I found - you'd probably do something smarter.
SQL> create or replace procedure housekeeping (par_schemaname in varchar2)
2 is
3 l_str varchar2(500);
4 l_rc sys_refcursor;
5 l_table_name varchar2(30);
6 begin
7 l_str := 'select table_name from ' ||
8 dbms_assert.schema_name(upper(par_schemaname)) ||
9 '.table_name where type = ''PERMANENT'' and rownum < 200';
10 open l_rc for l_str;
11
12 loop
13 fetch l_rc into l_table_name;
14 exit when l_rc%notfound;
15
16 dbms_output.put_line(l_table_name);
17 end loop;
18 close l_rc;
19 end;
20 /
Procedure created.
Testing:
SQL> set serveroutput on
SQL> exec housekeeping('SCOTT');
EMP
BONUS
PL/SQL procedure successfully completed.
SQL>

provide Select statement in procedure parameter

Hi i'm working on this query in oracle and i need to provide many id to a procedure from a table. how can i provide each id from a table to my procedure. sory i'm kinda new at this im completely lost i dont know what to search.
here's
Procedure
PROCEDURE procedname(in_id in VARCHAR2)
select id from mytable
Here's what i tryed
execute procedname(select id from mytable);
but did no work
Is there a way to achive this?
Hope somone help me out with this
You can pass a collection of numbers. Here is an example on how to pass.
--sys.odcinumberlist is a collection which can hold numbers..
create procedure sp_test(i_id in sys.odcinumberlist)
as
l_cnt int;
begin
select count(*)
into l_cnt
from TABLE(i_id); /* the TABLE keyword is used to unfold the collection of numbers as rows..*/
dbms_output.put_line(l_cnt);
end;
/
--calling the stored procedure
begin
dbms_output.enable;
sp_test(sys.odcinumberlist(1,2,3,4,5,6)); /* here i am passing a list of numbers from 1 to 6*/
--the procedure will count the number of elements in the input collection which is 6
end;
/
You cannot directly use a SQL statement as an argument for a procedure or function. Since that needs an INTO clause in order to return the content of the SELECT statement. Your case suggests a CURSOR as needs to return all the records at a time. For this, a possible sample solution using SYS_REFCURSOR as an IN/OUT(or just OUT) type of parameter would be ;
SQL> CREATE TABLE mytable( id VARCHAR2(1) );
SQL> INSERT INTO mytable VALUES('A');
SQL> INSERT INTO mytable VALUES('B');
SQL> CREATE OR REPLACE PROCEDURE Convert_ID(p_myrecordset IN OUT SYS_REFCURSOR) AS
BEGIN
OPEN p_myrecordset FOR
SELECT id, ASCII( id )
FROM mytable
ORDER BY id;
END;
/
SQL> SET SERVEROUTPUT ON;
SQL> DECLARE
l_cursor SYS_REFCURSOR;
l_value1 mytable.id%TYPE;
l_value2 INT;
BEGIN
Convert_ID(p_myrecordset => l_cursor);
LOOP
FETCH l_cursor
INTO l_value1, l_value2;
EXIT WHEN l_cursor%NOTFOUND;
DBMS_OUTPUT.PUT_LINE(l_value1 || ' - ' || l_value2 );
END LOOP;
CLOSE l_cursor;
END;
/
A - 65
B - 66
Demo
To take each id from some table and call sometable(id), a PL/SQL loop would be something like this:
begin
for r in (
select id from sometable
)
loop
procedname(r.id);
end loop;
end;

fetching table data into a table using cursor

I have a table called phonebook and it has two columns (firstName, LastName). I want to create a table of lastName index by firstName using cursor, and I wrote this code:
CREATE OR REPLACE PROCEDURE proc1 AS
TYPE tableNames IS TABLE OF VARCHAR2(20) INDEX BY VARCHAR(20);
v1 tableNames;
v_firstName PHONEBOOK.FIRSTNAME%TYPE;
v_lastName PHONEBOOK.LASTNAME%TYPE;
CURSOR c_name IS SELECT FIRSTNAME, LASTNAME FROM PHONEBOOK;
BEGIN
OPEN c_name;
LOOP
FETCH c_name INTO v_firstName, v_lastName;
EXIT WHEN c_name%NOTFOUND;
v1(v_firstName) := v_lastName;
END LOOP;
FOR idx IN v1.FIRST..v1.LAST
LOOP
DBMS_OUTPUT.PUT_LINE (v1(idx));
END LOOP;
CLOSE c_name;
END;
/
It has been successfully compiled. When I run this procedure it should print lastNames which stored in the tableNames but it gave me an error:
ORA-06502 "PL/SQL: numeric or value error"
Cause: An arithmetic, numeric, string, conversion, or constraint error
occurred. For example, this error occurs if an attempt is made to
assign the value NULL to a variable declared NOT NULL, or if an
attempt is made to assign an integer larger than 99 to a variable
declared NUMBER(2).
Action: Change the data, how it is manipulated, or how it is declared so
that values do not violate constraints.
Please help me to solve this problem
Not FOR, but WHILE. Also, I used cursor FOR loop as a source; easier to write & maintain.
SQL> create table phonebook (firstname varchar2(10), lastname varchar2(10));
Table created.
SQL> insert into phonebook
2 select 'Little', 'Foot' from dual union all
3 select 'Mc' , 'Donalds' from dual;
2 rows created.
SQL> create or replace procedure proc1 as
2 type tablenames is table of varchar2(10) index by varchar2(10);
3 v1 tablenames;
4 idx varchar2(10);
5 begin
6 for cur_r in (select firstname, lastname
7 from phonebook
8 )
9 loop
10 v1(cur_r.firstname) := cur_r.lastname;
11 end loop;
12
13 idx := v1.first;
14 while idx is not null loop
15 dbms_output.put_line(v1(idx));
16 idx := v1.next(idx);
17 end loop;
18 end;
19 /
Procedure created.
SQL> exec proc1;
Foot
Donalds
PL/SQL procedure successfully completed.
SQL>

Oracle stored procedure query like not working with cursor

I am new to oracle and trying to create a stored procedure with the following pl/sql code.
What is wrong with the code?when i replace the searchString with hard code value of '1605%' then the query is executed but not with the variable.
create or replace PACKAGE BODY MAT_INFO AS
PROCEDURE mat_details(mat_id IN varchar, mat_cur OUT SYS_REFCURSOR) AS
searchString varchar2(700);
BEGIN
searchString := ''''||mat_id||'%''';
OPEN mat_cur FOR SELECT mi.* FROM S_JAMM_MAT_INFO mi WHERE mi.MAT_ID LIKE searchString;
END mat_details;
END MAT_INFO;
Can anyone help me what am i doing wrong here?
Thanks
You are using unnecessary quotes:
SQL> declare
2 mat_id varchar2(100) := 'X';
3 searchString varchar2(100) := ''''||mat_id||'%''';
4 searchString2 varchar2(100) := ''||mat_id||'%';
5 num number;
6 begin
7 select count(1)
8 into num
9 from dual
10 where 'X' like searchString;
11 --
12 dbms_output.put_line('1. num= ' || num);
13 --
14 select count(1)
15 into num
16 from dual
17 where 'X' like searchString2;
18 --
19 dbms_output.put_line('2. num= ' || num);
20 end;
21 /
1. num= 0
2. num= 1
PL/SQL procedure successfully completed.
SQL>
Your double quoting could be useful if you would use a dynamic SQL, but in your static query it means that you are looking for a pattern containing quotes as part of the string to look for.
create or replace PACKAGE BODY MAT_INFO AS
PROCEDURE mat_details(
i_mat_id IN varchar,
mat_cur OUT SYS_REFCURSOR
)
AS
BEGIN
OPEN mat_cur FOR
SELECT *
FROM S_JAMM_MAT_INFO
WHERE MAT_ID LIKE i_mat_id || '%';
END mat_details;
END MAT_INFO;
/
You can try to change the procedure like below.
CREATE OR REPLACE PACKAGE BODY MAT_INFO AS
PROCEDURE MAT_DETAILS(MAT_ID IN VARCHAR, MAT_CUR OUT SYS_REFCURSOR) AS
SEARCHSTRING VARCHAR2(700);
CURSOR MAT_CUR (SEARCHSTRING VARCHAR) IS
SELECT MI.* FROM S_JAMM_MAT_INFO MI WHERE MI.MAT_ID LIKE SEARCHSTRING;
BEGIN
FOR DATA IN MAT_CUR(MAT_ID)
LOOP
--YOUR CODE
END LOOP;
END MAT_DETAILS;
END MAT_INFO;

Resources