Simple Oracle stored procedure - oracle

I have this SQL query:
select title
from DEPARTMENT;
I tried to write a stored procedure:
create PROCEDURE select_some
(whats VARCHAR2 ,c_select_some OUT SYS_REFCURSOR)
AS
BEGIN
OPEN c_select_some FOR
SELECT whats
FROM department;
END select_some;
/
But where I execute it with "title" parameter I got 8 rows with 'title' instead actual content. What's wrong?
Execution:
var whats varchar2(20)
variable whats = 'Title'
variable mycursor refcursor;
exec select_some (:whats, mycursor);

For this, you need to use dynamic SQL.
Something like this
create or replace procedure select_from_department(
col_name in varchar2,
c_res out sys_refcursor
)
is
l_sql varchar2(300);
begin
l_sql := 'select ' || dbms_assert.simple_sql_name(col_name) || ' from departments';
open c_res for l_sql ;
end;
DEMO

Related

How can I make table name from two string column?

I need to make a PL/SQL script.
The inputs are a schema name and a table name. How can I make it to a table name?
So e.g. I'd like to do this:
create or replace procedure proc(schema in varchar2, table in varchar2) is
begin
select * from 'schema.table';
end;
begin
proc('db', 'items');
end;
So I'd like to get everything from db.items.
I've tried concat, ( 'schema' || '.' || 'table'), put it in a variable, but non of these has worked.
What you need is dynamic sql. Example that will return and print the count of rows (you can change it accordingly to your needs):
SQL> set serveroutput on -- to be able to see the printed results.
SQL> create or replace procedure proc(p_schema in varchar2, p_table in varchar2) is
v_sql varchar2(100);
v_result number;
begin
v_sql := 'select count(*) from :1' || '.' || ':2';
EXECUTE IMMEDIATE v_sql into v_result USING p_schema, p_table;
DBMS_OUTPUT.PUT_LINE ('Total rows in table: '|| v_result );
end;

How to pass a string list to Stored Procedure In Olracle

How I can pass a string list to stored procedure?
this is my Stored Procedure:
CREATE OR REPLACE PROCEDURE sp_search (p_name IN VARCHAR2,
r_cursor SYS_REFCURSOR)
AS
BEGIN
OPEN cursor FOR SELECT name
FROM tableN
WHERE name IN (p_name);
END;
Example:
var c_ref refcursor;
sp_search('Andy,Marty,miky',:c_ref);
print c_ref;
I think, this should do it
CREATE OR REPLACE PROCEDURE sp_search (
p_name IN VARCHAR2,
r_cursor OUT SYS_REFCURSOR)
AS
Declare
v_sql VARCHAR2(200);
BEGIN
v_sql := 'SELECT name FROM table WHERE name IN (' || p_name || ')';
OPEN r_cursor FOR v_sql;
END;
Only make sure that when you pass Andy,Marty,miky, you add ' so that final sql looks like
SELECT name FROM table WHERE name IN ('Andy','Marty','miky')

Passing table name inside proc to store its row count into a variable

I want to write a simple pl/sql procedure which will take a table name as input and it will store the table row count into a variable . I have written the bellow code :
CREATE OR REPLACE procedure ATT_REP.proc_compare2(table_name IN varchar2)
is
cnt NUMBER(30);
begin
execute immediate 'select count(*) from '||table_name||' into '||cnt ;
dbms_output.put_line(cnt);
end;
/
while executing i am getting 'PLS-00357: Table,View Or Sequence reference 'CES_ODS.ENTITY' not allowed in this context' error.
Please suggest what am i doing wrong . How can i make it working .
Try the following:
CREATE OR REPLACE PROCEDURE ATT_REP.proc_compare2 (table_name IN VARCHAR2)
IS
cnt NUMBER (30);
sql_stmt VARCHAR2 (200);
BEGIN
sql_stmt := 'select count(*) from ' || table_name;
EXECUTE IMMEDIATE sql_stmt INTO cnt;
DBMS_OUTPUT.put_line (cnt);
END;
/

Oracle Stored Procedure

My question is pretty basic but I am complete newbie to stored procedure and need to get around quickly. Any help will be appreciated,
Below is the current stored procedure we have,
PROCEDURE get_something(
type IN VARCHAR2,
value IN VARCHAR2,
i_type OUT VARCHAR2,
i_id OUT VARCHAR2)
AS
TYPE t_array
IS
TABLE OF VARCHAR2(320);
identifers t_array;
column_name VARCHAR2(32);
info_qry VARCHAR2(500);
top_row_qry VARCHAR2(500);
BEGIN
identifers := t_array('ABC');
column_name := get_column_name(type);
info_qry := 'select INS.i_id, INS.model from table1 INS where INS.'||column_name||'='''||value||''' order by INS.version desc';
top_row_qry := 'select * from ('||info_qry||') where rownum<=1';
EXECUTE immediate top_row_qry INTO i_id, i_type;
EXCEPTION
WHEN OTHERS THEN
i_id := NULL;
i_type := NULL;
END get_something;
Now when I execute this procedure, it gives me one record due to the rownum condition.
My requirement is to remove the rownum from the top_row_qry, so result would be multiple rows.
I want to store each field into some variable out of which I will use one of the variable for some comparison in the procedure itself.
So basically i want to store the results which I can later loop over and compare with a list of values.
Also, I need to define the list of values in this procedure itself.
Something like below:
list_of_vals:= t_array('ABC','XYZ');
Can anyone help me on this.
I guess you need to use cursor as OUT parameter for your procedure and later use it for your requirement.
Also for "I need to define the list of values in this procedure itself."
you can use a collection the way I have used in the procedure code (v_array).
You can then use a loop to traverse through multiple values for the v_array.
CREATE ORE REPLACE PROCEDURE get_something(type IN VARCHAR2,
value IN VARCHAR2,
out_param OUT sys_refcursor)
AS
TYPE t_array IS TABLE OF VARCHAR2(320);
v_array t_array:=t_array();
-- identifers t_array;
column_name VARCHAR2(32);
info_qry VARCHAR2(500);
top_row_qry VARCHAR2(500);
BEGIN
--To define multiple values for a collection e.g. ABC, XYZ
v_array.EXTEND(2) ;
v_array(1):='ABC' ;
v_array(2):='XYZ' ;
--identifers := t_array('ABC') ;
column_name := get_column_name(TYPE) ;
info_qry := 'select INS.i_id, INS.model from table1 INS where INS.'||column_name||'='''||VALUE||''' order by INS.version desc';
top_row_qry := 'select * from ('||info_qry||')' ;
OPEN out_param FOR top_row_qry ;
EXCEPTION
WHEN OTHERS THEN
OPEN out_param FOR 'select null, null from dual' ;
END get_something ;
/
--To execute the procedure
DECLARE
lv_type VARCHAR2(200);
lv_id NUMBER;
lv_cur SYS_REFCURSOR;
BEGIN
get_something('param1','param2',lv_cur);
LOOP
FETCH lv_cur INTO lv_id,lv_type;
EXIT WHEN lv_cur%NOTFOUND;
--Do something.....
END LOOP;
END;

PL/SQL print out ref cursor returned by a stored procedure

How can I fetch from a ref cursor that is returned from a stored procedure (OUT variable) and print the resulting rows to STDOUT in SQL*PLUS?
ORACLE stored procedure:
PROCEDURE GetGrantListByPI(p_firstname IN VARCHAR2, p_lastname IN VARCHAR2,
p_orderby IN VARCHAR2, p_cursor OUT grantcur);
PL/SQL:
SET SERVEROUTPUT ON;
DECLARE
TYPE r_cursor IS REF CURSOR;
refCursor r_cursor;
CURSOR grantCursor IS
SELECT last_name, first_name
FROM ten_year_pis
WHERE year_added = 2010;
last_name VARCHAR2(100);
first_name VARCHAR2(100);
BEGIN
OPEN grantCursor;
FETCH grantCursor INTO last_name, first_name;
WHILE grantCursor%FOUND LOOP
PMAWEB_PKG.GetGrantListByPI(last_name, first_name, 'last_name', refCursor);
--HOW DO I LOOP THROUGH THE RETURNED REF CURSOR (refCursor)
--AND PRINT THE RESULTING ROWS TO STDOUT?
FETCH grantCursor into last_name, first_name;
END LOOP;
CLOSE grantCursor;
END;
/
Note: This code is untested
Define a record for your refCursor return type, call it rec. For example:
TYPE MyRec IS RECORD (col1 VARCHAR2(10), col2 VARCHAR2(20), ...); --define the record
rec MyRec; -- instantiate the record
Once you have the refcursor returned from your procedure, you can add the following code where your comments are now:
LOOP
FETCH refCursor INTO rec;
EXIT WHEN refCursor%NOTFOUND;
dbms_output.put_line(rec.col1||','||rec.col2||','||...);
END LOOP;
You can use a bind variable at the SQLPlus level to do this. Of course you have little control over the formatting of the output.
VAR x REFCURSOR;
EXEC GetGrantListByPI(args, :x);
PRINT x;
If you want to print all the columns in your select clause you can go with the autoprint command.
CREATE OR REPLACE PROCEDURE sps_detail_dtest(v_refcur OUT sys_refcursor)
AS
BEGIN
OPEN v_refcur FOR 'select * from dummy_table';
END;
SET autoprint on;
--calling the procedure
VAR vcur refcursor;
DECLARE
BEGIN
sps_detail_dtest(vrefcur=>:vcur);
END;
Hope this gives you an alternate solution
More easier option is to use DBMS_SQL.return_result();
Lets say your package / procedure / cursor spec is as below.
create or replace PACKAGE my_package IS
TYPE my_ref_cursor_type IS REF CURSOR;
PROCEDURE my_procedure (
p_in_param1 IN VARCHAR2,
p_in_param2 IN VARCHAR2,
p_in_param3 IN VARCHAR2,
p_my_ref_cursor OUT my_ref_cursor_type,
p_err_code OUT NUMBER,
p_err_msg OUT VARCHAR2
);
END my_package;
Try this to invoke the procedure from your sql developer WORKSHEET
SET SERVEROUTPUT ON;
DECLARE
P_MY_REF_CURSOR my_schema.my_package.my_ref_cursor_type;
P_ERR_CODE NUMBER;
P_ERR_MSG VARCHAR2(200);
BEGIN
my_package.my_procedure(
'VALUE1',
'VALUE2',
'VALUE3',
P_MY_REF_CURSOR => P_MY_REF_CURSOR,
P_ERR_CODE => P_ERR_CODE,
P_ERR_MSG => P_ERR_MSG
);
DBMS_OUTPUT.PUT_LINE(P_ERR_MSG);
DBMS_OUTPUT.PUT_LINE(P_ERR_CODE);
DBMS_SQL.return_result(P_MY_REF_CURSOR);
END;
Hope this helps !
There are many ways for displaying the sys_refcursor result set and one of them that is so easy is using SQL Developer to fetch sys_refcursor and print output which are:
Create a test function to print its result
Execute the function
View the output
Verify the result set

Resources