Procedure created with compilation errors in oracle.? - oracle

I wrote simple stored procedure in oracle. but its shows procedure created with compilation errors.
My code is:
CREATE OR REPLACE PROCEDURE PRC_SELECT
AS
BEGIN
SELECT * FROM tb_name;
END;
/
Please help me to solve this problem.

This is a very basic skeleton, for your requirement.
CREATE OR REPLACE PROCEDURE PRC_SELECT(p_OLD IN VARCHAR2)
AS
my_rec tb_name%rowtype;
BEGIN
SELECT * into my_rec FROM tb_name WHERE old = p_OLD;
END;
/
my_rec will be created as a PL/SQL type whose structure would be table tb_name's structure!

a procedure cannot do a select * back to the screen.
you would have to bulk collect it into a collection and return it or open a cursor and return that.
a procedure is pl/sql, which doesn't directly write to the screen.
if you want it, you can use dbms_output.put_line to write each record.
you might also want to look into pipelined functions, which can be used in SQL later.
it depends what you're requirements are really.

If you really want to read all the rows in tb_name you could try:
CREATE OR REPLACE PROCEDURE PRC_SELECT
AS
BEGIN
FOR aRow IN (SELECT * FROM tb_name)
LOOP
DBMS_OUTPUT.PUT_LINE('Retrieved ' || aRow.SOME_FIELD);
END LOOP;
END;
Note that this may produce a lot of output if there are many rows in tb_name.
Share and enjoy.

Related

Testing native dynamic SQL in Oracle before execution

I have implemented a certain feature in my application where the user can compose queries dynamically from the user interface by pushing around buttons and inserting some values here and there.
The user will not see the generated SQL statement at all.
I was wondering if there is a way to perhaps check the syntax and grammar (e.g. he opened a parantheses '(' and forgot to close it ) of the dynamically generated SQL to ensure that no run-time compilation errors would happen before actually executing the statement using EXECUTE IMMEDIATE.
You could use the dbms_sql.parse procedure to parse the SQL statement assuming the statement is DML not DDL. It would be rather unusual to parse a dynamic SQL statement using the dbms_sql package and then use EXECUTE IMMEDIATE to execute it rather than using dbms_sql.execute but nothing prevents you from mixing dbms_sql and execute immediate.
The code to just parse the SQL statement would be something like
DECLARE
l_cursor integer;
l_sql_stmt varchar2(1000) := <<some SQL statement>>;
BEGIN
l_cursor := dbms_sql.open_cursor;
dbms_sql.parse( l_cursor, l_sql_stmt, dbms_sql.native );
dbms_sql.close_cursor( l_cursor );
END;
You can also use explain plan, this is basically doing the first step of the execution.
SQL> explain plan for select * from dual;
Explained.
SQL is valid, you can also use the explain tables to get the tables, views etc, maybe even estimated run time ...
SQL> explain plan for select * from duall;
explain plan for select * from duall
*
ERROR at line 1:
ORA-00942: table or view does not exist
SQL is invalid, this is why ...
you can also use it in a dynamic statement
SQL> begin execute immediate 'explain plan for ' || ' select * from dual'; end;
2 /
PL/SQL procedure successfully completed.
As always use error-handling, e.g. write a little error log creater package or procedure what u call when it's needed.
DECLARE
my_stmt VARCHAR2(4000):='this will contain my statements';
BEGIN
'begin' || my_stmt || 'end';
EXCEPTION
WHEN OTHERS THEN
prc_my_error_log_creator();
END;
in the log_creator use for example the DBMS_UTILITY.FORMAT_ERROR_BACKTRACE() func to get the stack's contain.
Regards

How to get refcursor result/output to show as text?

I'm trying to call a stored procedure in Oracle and show the results of the call, the problem is that it crashes on the line FETCH v_cur into v_a; with error: ORA-06504: PL/SQL: Return types of Result Set variables or query do not match.
I guess the output of the query does not match v_a VARCHAR2(100), but I don't know what to put there instead. The stored procedure that's being called does a join of several tables and selects more than 20+ different columns belonging to different tables. So what I would want is to just view the output of the query without having to refer to each result column separately. How I would go and do this ?
I'm using SQL Navigator (not that important I guess).
DECLARE
v_cur SYS_REFCURSOR;
v_a VARCHAR2(100);
BEGIN
pkg_get_results.get_rows(v_cur,to_date('2012/04/12', 'yyyy/mm/dd'),to_date('2012/04/12', 'yyyy/mm/dd'), '','','','');
LOOP
FETCH v_cur into v_a; -- what to put here ?
EXIT WHEN v_cur%NOTFOUND;
dbms_output.put_line(v_a );
END LOOP;
CLOSE v_cur;
END;
SQL Navigator does have the ability to do this for you. How to do it exactly depends on your version of Navigator, and it's conceivable (though I don't know) some versions may not have it.
Instructions can be found in this thread: http://sqlnavigator.inside.quest.com/thread.jspa?threadID=2466
Incidentally, Toad also has this ability.

How to test an Oracle Stored Procedure with RefCursor return type?

I'm looking for a good explanation on how to test an Oracle stored procedure in SQL Developer or Embarcardero Rapid XE2. Thank you.
Something like
create or replace procedure my_proc( p_rc OUT SYS_REFCURSOR )
as
begin
open p_rc
for select 1 col1
from dual;
end;
/
variable rc refcursor;
exec my_proc( :rc );
print rc;
will work in SQL*Plus or SQL Developer. I don't have any experience with Embarcardero Rapid XE2 so I have no idea whether it supports SQL*Plus commands like this.
Something like this lets you test your procedure on almost any client:
DECLARE
v_cur SYS_REFCURSOR;
v_a VARCHAR2(10);
v_b VARCHAR2(10);
BEGIN
your_proc(v_cur);
LOOP
FETCH v_cur INTO v_a, v_b;
EXIT WHEN v_cur%NOTFOUND;
dbms_output.put_line(v_a || ' ' || v_b);
END LOOP;
CLOSE v_cur;
END;
Basically, your test harness needs to support the definition of a SYS_REFCURSOR variable and the ability to call your procedure while passing in the variable you defined, then loop through the cursor result set. PL/SQL does all that, and anonymous blocks are easy to set up and maintain, fairly adaptable, and quite readable to anyone who works with PL/SQL.
Another, albeit similar way would be to build a named procedure that does the same thing, and assuming the client has a debugger (like SQL Developer, PL/SQL Developer, TOAD, etc.) you could then step through the execution.
In SQL Developer you can right-click on the package body then select RUN. The 'Run PL/SQL' window will let you edit the PL/SQL Block. Clicking OK will give you a window pane titled 'Output Variables - Log' with an output variables tab. You can select your output variables on the left and the result is shown on the right side. Very handy and fast.
I've used Rapid with T-SQL and I think there was something similiar to this.
Writing your own delcare-begin-end script where you loop through the cursor, as with DCookie's example, is always a good exercise to do every now and then. It will work with anything and you will know that your code works.
In Toad 10.1.1.8 I use:
variable salida refcursor
exec MY_PKG.MY_PRC(1, 2, 3, :salida) -- 1, 2, 3 are params
print salida
Then, Execute as Script.
I think this link will be enough for you. I found it when I was searching for the way to execute oracle procedures.
The link to the page
Short Description:
--cursor variable declaration
variable Out_Ref_Cursor refcursor;
--execute procedure
execute get_employees_name(IN_Variable,:Out_Ref_Cursor);
--display result referenced by ref cursor.
print Out_Ref_Cursor;
create or replace procedure my_proc( v_number IN number,p_rc OUT SYS_REFCURSOR )
as
begin
open p_rc
for select 1 col1
from dual;
end;
/
and then write a function lie this which calls your stored procedure
create or replace function my_proc_test(v_number IN NUMBER) RETURN sys_refcursor
as
p_rc sys_refcursor;
begin
my_proc(v_number,p_rc);
return p_rc;
end
/
then you can run this SQL query in the SQLDeveloper editor.
SELECT my_proc_test(3) FROM DUAL;
you will see the result in the console right click on it and cilck on single record view and edit the result you can see the all the records that were returned by the ref cursor.

how do oracle stored procedures (w/ cursors) work?

I have a following oracle stored procedure
CREATE OR REPLACE
PROCEDURE getRejectedReasons
(
p_cursor IN OUT SYS_REFCURSOR)
AS
BEGIN
OPEN p_cursor FOR SELECT * FROM reasons_for_rejection;
END;
However, when I run this stored procedure in sql-developer then I dont see anything. I just see something like this:
Connecting to the database oracleLocal.
Process exited.
Disconnecting from the database oracleLocal.
I'm coming from MS sql server and am used to seeing actual results when running a stored procedure like this. Is this stored procedure not returning results because I am using a cursor??
The stored procedure is returning something it's just you aren't doing anything with the results.
You can do this simply by running the following script in SQLDeveloper:
VARIABLE csr REFCURSOR;
EXEC getRejectedReasons(:csr); -- the colon identifies the parameter as a variable
PRINT csr;
Another method is to fetch each row and do some sort of processing:
DECLARE
-- sys_refcursor is weakly typed
refcsr SYS_REFCURSOR;
-- define a record so we can reference the fields
rej_rec Reasons_for_Rejection%ROWTYPE;
BEGIN
getRejectedReasons(refcsr);
-- loop through the results
LOOP
-- gets one row at a time
FETCH refcsr INTO rej_rec;
-- if the fetch doesn't find any more rows exit the loop
EXIT WHEN refcsr%NOTFOUND;
-- Do something here.
-- For example : DBMS_OUTPUT.PUT_LINE(rej_rec.reason_desc);
END LOOP;
END;
You opened the cursor. You didn't select anything from it, update it, or advance it.
All open does, effectively, to select the matching rows into temporary memory, so you can advance the cursor row by row. Which you didn't do.
One of the differences between Oracle and SQL Server is that the latter returns result sets naturally. I'd use a function, by the way.
In Oracle, functions typically return a single element. Cursors came later.
There's some documentation online that will help you understand the use of refcursor bind variables. Here's one such for SQL*Plus:
http://download.oracle.com/docs/cd/B19306_01/server.102/b14357/ch5.htm#sthref1122
I think in SQL Developer you can do the same thing with autoprint on, although I haven't tested that.
Found a blog that also discusses something similar:
http://vadimtropashko.wordpress.com/cursors/
ETA: Ok. Ignore what I wrote. Listen to someone else. Apparently it's wrong, as I got down voted.
What tpdi said is correct. You have to do something with the cursor after you declare it.
Here's an example using two cursors in nested loops
PROCEDURE update_insert_tree (exid_in IN NUMBER, outvar_out OUT VARCHAR2)
IS
nxtid NUMBER;
phaseid NUMBER;
rowcounter1 NUMBER;
BEGIN
rowcounter1 := 0;
outvar_out := 0;
FOR acur IN (SELECT dept_exercise_id, phase
FROM ep_dept_exercise
WHERE exercise_id = exid_in)
LOOP
<<dept_loop>>
FOR thecur IN (SELECT document_name, thelevel, sortnum, type_flag,
ex_save_id
FROM ep_exercise_save
WHERE exercise_id = exid_in)
LOOP
phaseid := acur.phase;
IF phaseid = 0
THEN
phaseid := 10;
UPDATE ep_dept_exercise
SET phase = 10
WHERE dept_exercise_id = acur.dept_exercise_id;
END IF;
<<doc_loop>>

Dynamic PL/SQL

In PL/SQL,I would like to pass a source as well as the target schema as a parameter to a stored procedure. For source we can use:
PROCEDURE select_from_schema( the_schema VARCHAR2)
IS
TYPE my_cursor_type IS REF CURSOR;
my_cursor my_cursor_type;
BEGIN
OPEN my_cursor FOR 'SELECT my_field FROM '||the_schema||'.my_table';
-- Do your FETCHes just as with a normal cursor
CLOSE my_cursor;
END;
For the target insert or update statement, how can we use that schema inside that insert or update statement....Does anyone know how could I do that???
P.S. Excuse me; I am a beginner and must get some functions written quickly.
You can do the same thing for an INSERT or UPDATE that you did for a SELECT - use dynamic SQL like this:
EXECUTE IMMEDIATE 'INSERT INTO '||target_schema||'.my_table (col1,col2...) VALUES(:val1, :val2...)' USING my_row.col1, my_row.col2...;

Resources