How to call a stored procedure in pl/sql developer - oracle

I am new at this and have a simple question.
I have created a procedure like so in pl/sql developer
CREATE OR REPLACE PROCEDURE myproc2 AS
BEGIN
SELECT cd_desc des, cd_value cd FROM v_codes WHERE cd_type='CVS02'
END;
Now I want to call the procedure and see the output however when I run this
BEGIN
myproc2;
END;
in Pl/sql I am getting an error saying object myproc2 is invalid
How do I call a stored procedure in PL/SQL?

You're calling it right, but the procedure is wrong. If you check its status, it is invalid.
In PL/SQL, a SELECT requires INTO:
CREATE OR REPLACE PROCEDURE myproc2 AS
l_cd_desc v_codes.cd_desc%type;
l_cd_value v_codes.cd_value%type;
BEGIN
SELECT v.cd_desc, v.cd_value
INTO l_cd_desc, l_cd_value
FROM v_codes v
WHERE v.cd_type = 'CVS02';
END;
Beware of possible NO_DATA_FOUND or TOO_MANY_ROWS exception.
Also, although it'll now run OK (I guess), you won't see anything because it is unknown what you'll do next. You could, for example, choose to display values you fetched. In that case, add
<snip>
WHERE v.cd_type = 'CVS02';
dbms_output.put_line(l_cd_desc ||', '|| l_cd_value);
END;
Don't forget to enable serveroutput.
As you commented, you got too_many_rows. How to handle it? It depends on what you want to do. One option is to switch to a cursor FOR loop; now you don't need local variables and - as there's no SELECT statement itself - no INTO clause either:
CREATE OR REPLACE PROCEDURE myproc2
AS
BEGIN
FOR cur_r IN (SELECT v.cd_desc, v.cd_value
FROM v_codes v
WHERE v.cd_type = 'CVS02')
LOOP
DBMS_OUTPUT.put_line (cur_r.cd_desc || ', ' || cur_r.cd_value);
END LOOP;
END;

One great thing about Oracle SQL Developer is the GUI and that it does things for you.
You can open a sheet and run it the traditional way:
BEGIN
PROCEDURENAME(PARAM);
END;
or you can use the GUI, find the object with the (View->) Find DB object, find it, click on it and use the green arrow in the toolbar. It will open a UI for any parameters you used within the procedure.

In SQL Developer, if you want to see the output then you can return a cursor:
CREATE OR REPLACE PROCEDURE myproc2(
o_cursor OUT SYS_REFCURSOR
)
AS
BEGIN
OPEN o_cursor FOR
SELECT cd_desc AS des,
cd_value AS cd
FROM v_codes
WHERE cd_type='CVS02'; -- You need a ; statement terminator here.
END;
/
Then you can use:
-- Declare a cursor bind variable
VARIABLE cur SYS_REFCURSOR;
BEGIN
-- Call the cursor outputting into the bind variable.
myproc2(:cur);
END;
/
-- Print the cursor
PRINT :cur;
And run it as a script (using F5).

Related

How to write an Oracle procedure with a select statement (Specifically on SQL Developer)?

I want to create a simple Oracle Stored procedure on SQL Developer that will return some records on a simple select query. I do not want to pass in any parameter, but I just want the Records to be returned back from the procedure into a result set -> a suitable variable.
I have been trying to use the following syntax :
create or replace PROCEDURE Getmarketdetails2(data OUT varchar2)
IS
BEGIN
SELECT *
into data
from dual;
END Getmarketdetails2;
But it gives me an error while I try to execute with the following exec statement -->
Declare a Varchar2;
exec Getmarketdetails2(a);
Error: PLS-00103: Encountered the symbol "end-of-file" when expecting "something else".
Cause: Usually a PL/SQL compilation error.
Appreciate if anyone can help me out of this long pending situation! I have tried enough to find a basic guide to create a simple Oracle stored procedure and execute it in SQL Developer, but none of them answer to the point!!
You want:
DECLARE
a VARCHAR2(4000); -- Give it a size
BEGIN -- Begin the anonymous PL/SQL block
Getmarketdetails2(a); -- Call the procedure
DBMS_OUTPUT.PUT_LINE( a ); -- Output the value
END; -- End the anonymous PL/SQL block
/ -- End the PL/SQL statement
or:
VARIABLE a VARCHAR2(4000); -- Create a bind variable
EXEC Getmarketdetails2(:a); -- Execute the procedure using the bind variable
PRINT a -- Print the bind variable
Assuming an up-to-date Oracle version, you can use dbms_sql.return_result()
create or replace PROCEDURE Getmarketdetails2
IS
c1 SYS_REFCURSOR;
BEGIN
OPEN c1 FOR
SELECT *
from dual;
DBMS_SQL.RETURN_RESULT(c1);
END Getmarketdetails2;
/
Then simply run
exec Getmarketdetails2
The only drawback is that SQL Developer only displays the result as text, not as a proper result grid.
This is how I return a cursor in Oracle
PROCEDURE GetAllData (P_CURSOR OUT SYS_REFCURSOR)
IS
BEGIN
OPEN P_CURSOR FOR
SELECT *
FROM TABLE ;
END GetAllData ;
Declare a Varchar2;
exec Getmarketdetails2(a);
Your procedure is ok;
Instead of above query, use below query to run sp:
Declare
a Varchar2(10);
Begin
Getmarketdetails2(a);
End;

PL/SQL - Cursor. Can't iterate through table (varchar argument)

I created a procedure to calculate the hashcode of a record (complete line of a table) and then update a column with the calculated hashcode number.
Here's my code at this point (which is based on some info I manage to gather from Google):
CREATE OR REPLACE PROCEDURE calcHashCode (inputTableString IN varchar2) IS
c_data varchar2(3000); --QUERY
c_cursor sys_refcursor; --CURSOR
c_record inputTableString%rowtype; -- Problem is here
BEGIN
c_data := 'SELECT * FROM ' || inputTableString;
OPEN c_cursor for c_data;
LOOP
FETCH c_cursor INTO c_record;
EXIT WHEN c_cursor%notfound;
-- will do stuff here with the records
dbms_output.put_line('stuff');
END LOOP;
CLOSE c_cursor;
END;
/
SHOW ERRORS
4/13 PLS-00310: with %ROWTYPE attribute, 'INPUTTABELA' must name a table, cursor or cursor-variable
4/13 PL/SQL: Item ignored
11/25 PLS-00320: the declaration of the type of this expression is incomplete or malformed
11/5 PL/SQL: SQL Statement ignored
So, my idea (for the final stage of the procedure) is to iterate through out the records, build a string with and then calculate the hashcode. After that, I'll run the update instruction.
The thing is at this point using a varchar as an argument and I'm not being able to iterate through the table in order to get my concatenate records.
dynamic cursors are the ugliest...
the problem is with that section:
c_data varchar2(3000); --QUERY
c_cursor sys_refcursor; --CURSOR
c_record inputTableString%rowtype;
i used something like this:
TYPE t_data IS REF CURSOR;
cr_data t_data;
cr_data_rec inputTableString%ROWTYPE; --that table need to be exists in compile time
the rest are good i think
Have you considered pushing the whole declaration and loop into an anonymous block that will then get executed by EXECUTE IMMEDIATE? You can then simplify your looping construct to a simple FOR loop too.
I'm away from my database at the moment, so excuse any syntax glitches, but something like
CREATE OR REPLACE PROCEDURE calcHashCode (inputTableString IN varchar2) IS
c_data varchar2(30000); --QUERY
BEGIN
c_data := '
BEGIN
FOR aRec IN
(SELECT * FROM ' || inputTableString ||' )
LOOP
--do your stuff
END LOOP;
END';
execute immediate c_Data;
END;
/
It may not be pretty, and your "Stuff" may not easily be able to be fit into this construct, but it IS feasible
You can do all this kind of stuff with PL/SQL package DBMS_SQL, however it is definitely not for beginners and you should start with something easier.
Examples for DBMS_SQL

Get input from user in PL/SQL procedure

I'm building a procedure which would require to get an input from user to print few details. But when I use & to get values it fails with errors. the logic is as follows..
DBMS_OUTPUT.PUT_LINE('Enter Y to display Unauthorized records OR N to skip the display');
--SELECT &1 INTO lv_choice FROM DUAL;
IF NOT ('&lv_choice'='Y') THEN
DBMS_OUTPUT.PUT_LINE ('RECORDS WILL NOT BE DISPLAYED');
ELSE
DBMS_OUTPUT.PUT_LINE ('RECORDS TO BE DISPLAYED ARE:');
......
I have tried using &1 into dual or directly calling &lv_choice which is failing with PLSQL internal errors.
Any methods to get input from user to proceed further in the procedure?
This isn't possible in PL/SQL - PL/SQL doesn't have access to the terminal(unless you do something like plug in Java or call your program from a something like SQL*Plus(in which you can use commands like ACCEPT/PROMPT before you run the procedure).
The & variables are substitution variables, and are specific to SQL*Plus, not PL/SQL
If you are using some UI Terminal like SQLDeveloper or TOAD, you can achieve it using below code:
CREATE OR REPLACE INPUTPROCEDURE (LV_CHOICE IN VARCHAR2)
AS
BEGIN
DBMS_OUTPUT.PUT_LINE('Enter Y to display Unauthorized records OR N to skip the display');
--SELECT &1 INTO lv_choice FROM DUAL;
IF lv_choice <> 'Y' THEN
DBMS_OUTPUT.PUT_LINE ('RECORDS WILL NOT BE DISPLAYED');
ELSE
DBMS_OUTPUT.PUT_LINE ('RECORDS TO BE DISPLAYED ARE:');
END INPUTPROCEDURE;
And Invoke the above Procedure like below:
DECLARE
dyn_stmt VARCHAR2(200);
b BOOLEAN := TRUE;
BEGIN
dyn_stmt := 'BEGIN INPUTPROCEDURE(:LV_CHOICE); END;';
EXECUTE IMMEDIATE dyn_stmt USING b;
END;

Oracle SQL Developer PL/SQL return an array

Devs,
I've searched everywhere I can, but I could not find solution to this simple problem.
Situation:
I need to write a procedure where it takes a column name as the input and return all the distinct values present in that column as output. And then I have to use this procedure in some c# code.
In MS server, it is very easy as it will directly give the set of results unlike in PL/SQL.
Script I could write (which is not giving me the result I need):
CREATE OR REPLACE
PROCEDURE GetCol(PARAM IN STRING, recordset OUT sys_refcursor)
AS
BEGIN
OPEN recordset FOR
SELECT DISTINCT(PARAM)
FROM my_table;
END
;
When I try to check the data in the recordset using this code:
DECLARE
l_cursor SYS_REFCURSOR;
l_sname VARCHAR2(50);
BEGIN
GetCol('col_name',l_cursor);
LOOP
FETCH l_cursor INTO l_sname;
EXIT WHEN l_cursor%NOTFOUND;
DBMS_OUTPUT.PUT_LINE(l_sname);
END LOOP;
CLOSE
Can someone help me with this code please.
You can also open a ref_cursor for a string value. Please take a look at this:
CREATE OR REPLACE PROCEDURE GetCol(PARAM IN VARCHAR2, recordset OUT sys_refcursor)
AS
QRY varchar2(100);
BEGIN
QRY := 'SELECT DISTINCT '||PARAM||' FROM my_table';
OPEN recordset FOR QRY;
END;
Then:
DECLARE
l_cursor SYS_REFCURSOR;
l_sname VARCHAR2(50);
BEGIN
GetCol('col_name',l_cursor);
LOOP
FETCH l_cursor INTO l_sname;
EXIT WHEN l_cursor%NOTFOUND;
DBMS_OUTPUT.PUT_LINE(l_sname);
END LOOP;
END;
Your problem is caused by ambiguity about what PARAM is in the procedure's SELECT statement:
CREATE OR REPLACE
PROCEDURE GetCol(PARAM IN STRING, recordset OUT sys_refcursor)
AS
BEGIN
OPEN recordset FOR
SELECT DISTINCT(PARAM) -- Ambiguity here
FROM my_table;
END;
Does PARAM refer to the table column or to the first parameter of the procedure? Oracle has assumed the parameter. You can explicitly say which like this:
SELECT DISTINCT(my_table.PARAM)
FROM my_table;
You could if appropriate (it probably isn't here) specify the procedure parameter instead:
SELECT DISTINCT(GetCol.PARAM)
FROM my_table;
Generally this is best avoided by:
always using table aliases in column references select statements, and
having a standard for parameter names that makes them less likely to clash e.g. P_PARAM.

Unable to execute oracle procedure in PLSQL Developer

I am having sample Procedure as Below
CREATE OR REPLACE PROCEDURE proc_Table1
BEGIN
SELECT 'Sample UserName' AS UserName
FROM Dual;
END;
Now I want to run this Proc in PLSQL developer.I tried the below but its generating error
begin
proc_Table1;
end;
Its Displaying
Thanks for the Help.
Any Idea why this Happens.
When you created the procedure, you should have been alerted to the fact that you had syntax errors. If you're going to run a SELECT statement, you need to do something with the results-- either populate a local variable or open a cursor or something else. The code you've posted is also missing the IS/AS keyword
CREATE OR REPLACE PROCEDURE proc_Table1
AS
l_username VARCHAR2(30);
BEGIN
SELECT 'Sample UserName' AS UserName
INTO l_username
FROM Dual;
END;
will be syntactically valid. It doesn't appear, however, to be particularly useful-- you procedure isn't modifying the database and has no way to communicate with the caller so it isn't doing anything meaningful. As a general principal, you would also generally want to use a simple PL/SQL assignment operator to populate a local variable rather than selecting from dual, i.e.
l_username := 'Sample UserName';
Try this, it should work:
CREATE OR REPLACE PROCEDURE proc_Table1(UserName OUT VARCHAR2)
AS
BEGIN
SELECT 'Sample UserName' INTO UserName
FROM Dual;
dbms_output.put_line(UserName);
END PROC_TABLE1;
-------------------------------
How to Execute
-------------------------------
declare
name varchar2(50);
result varchar2(100);
begin
proc_table1(name);
end;

Resources