PL SQL Procedure from Trigger - oracle

I created procedure GETDEL that select name from students , but when i try to call this procedure in trigger it says i gave wrong types of argument to call
I have been trying to pass (records) or (records OUT SYS_REFCURSOR) as a argument but it dont works
CREATE OR REPLACE PROCEDURE GETDEL(records OUT SYS_REFCURSOR) AS
BEGIN
OPEN records FOR
SELECT name FROM students;
END GETDEL;
CREATE OR REPLACE TRIGGER After_delete_student
AFTER DELETE ON TABLE2
FOR EACH ROW
DECLARE
rec sys_refcursor;
BEGIN
GETDELCZL();
END;

Your procedure contains a single parameter and, even though it's an out parameter, the calling procedure is responsible the defining it.
create or replace
trigger after_delete_student
after delete
on table2
for each row
declare
result_rec sys_refcursor;
begin
getdel(result_rec);
end;

Related

Why the select statement is not showing me table while executed in oracle?

I am new to oracle.I already have a table tempash.
So,I created a procedure to see the data of this table.
So,I created procedure as:
create or replace procedure offc.temp_sel(data1 varchar2) is
var1 varchar2(4000);
BEGIN
var1:='select * from offc.temp'||data1;
EXECUTE IMMEDIATE var1;
end;
So,I executed the statement but,it is not showing me anything.
exec offc.temp_sel('ash');
There is no any compilation error in my procedure.But why the select statement is not showing me data of that procedure?
Try adding out parameter:
create or replace procedure offc.temp_sel(data1 varchar2,result out sys_refcursor)
is
BEGIN
open result for 'select * from offc.temp'||data1;
end;
SQL> var rc refcursor
SQL> execute offc.temp_sel('ash',:rc)
PL/SQL procedure successfully completed.
SQL> print rc
You need to keep the result of the SELECT statement into a variable. As you perform SELECT * ..., you should put the result into a RECORD type but, as the result set contains more than 1 row, your variable needs to be a table of records.
In order to not be prone to error, the tables of records needs to be exactly like your table source structure.
CREATE OR REPLACE PROCEDURE OFFC.TEMP_SEL(DATA1 VARCHAR2) IS
VAR1 VARCHAR2(4000);
TYPE T_RESULT IS TABLE OF offc.temp%ROWTYPE;
-- defined the new type based on the structure of table TEMP from schema OFFC
v_result t_result;
-- define a variable of that type.
BEGIN
var1:='select * from offc.temp'||data1;
EXECUTE IMMEDIATE VAR1 BULK COLLECT INTO V_RESULT;
-- collect he result into the new variable
FOR I IN 1 ..v_result.count
LOOP
dbms_output.put_line(v_result(i).<<column_name from temp offc.table>>);
end loop;
-- loop through the variable(table of records) and display its content.
-- you need to replace the << ... >> with the name of your column from source tabel that you want to display.
end;
To execute the procedure, you should use:
set serveroutput on;
execute temp_sel( 'ash');
Best,
Mikcutu

Calling one procedure from another procedure

The code below is saved in a file named proc1.sql
DECLARE
B VARCHAR2(25);
C NUMBER;
PROCEDURE Get_manager_detailS(NO IN NUMBER,NAME OUT VARCHAR2,SAL1 OUT NUMBER)
IS
BEGIN
SELECT ENAME, SAL
INTO NAME, SAL1
FROM EMP
WHERE EMPNO = NO;
END;
BEGIN
Get_manager_detailS(7900,B,C);
DBMS_OUTPUT.PUT_LINE(B);
DBMS_OUTPUT.PUT_LINE(C);
END;
/
This procedure is stored in another file proc3.sql
PROCEDURE Test_Procedure()
IS
BEGIN
b varchar2(25);
c number;
DBMS_OUTPUT.PUT_LINE('CALLING');
Get_manager_details(7900,b,c);
END;
When I am running it in sqlplus, it is showing an error
SP2-0734 UNKNOWN COMMAND BEGINING PROCEDURE.. REST OF THE LINES IGNORED.
SP2-0042 UNKNOWN COMMAND" IS "..REST OF THE LINE IGNORED.
Creating a PROCEDURE/FUNCTION vs. ANONYMOUS BLOCK
Stored PROCEDURES/FUNCTIONS always starts with CREATE OR REPLACE ... and ends with END;
CREATE OR REPLACE serves as the implicit declare for stored functions and procedures, thus you dont have to write DECLARE anymore inside the block
An anonymous block starts with DECLARE and ends with END;
As for the code/block of codes saved in proc1.sql.
Your declaration is misplaced.You should place it after the end of
the procedure
Start the procedure with CREATE OR REPLACE PROCEDURE
Try This Block:
-- DECLARE
-- B VARCHAR2(25);
-- C NUMBER;
CREATE OR REPLACE PROCEDURE Get_manager_detailS(NO IN NUMBER,
NAME OUT VARCHAR2,
SAL1 OUT NUMBER)
IS
BEGIN
SELECT ENAME, SAL
INTO NAME, SAL1
FROM EMP
WHERE EMPNO = NO;
END; -- end of procedure
/
DECLARE -- start of anonymous block
B VARCHAR2(25);
C NUMBER;
BEGIN
Get_manager_detailS(7900,B,C);
DBMS_OUTPUT.PUT_LINE(B);
DBMS_OUTPUT.PUT_LINE(C);
END;
As for the procedure that will call the get_manager_details procedure.Its will be just the same as the anonymous block, the only difference will be is that it is stored
Base from what have you done already
If you will not declare parameters in your procedure, parenthesis are not necessary so remove it.
If you dont have output parameters that will catch the result of your procedure, you can use dbms_output.put_line as you have used in
the anonymous block above
variable declarations should be done after the IS keyword and before BEGIN statements, because as I have noted above CREATE OR
REPLACE ... IS is the implicit declare for the stored functions and
procedures
TRY THIS:
CREATE OR REPLACE PROCEDURE Test_Procedure
IS -- always start with CREATE OR REPLACE
b varchar2(25);
c number;
BEGIN
-- b varchar2(25); misplaced declarations
-- c number;
DBMS_OUTPUT.PUT_LINE('CALLING');
Get_manager_details(7900,b,c);
DBMS_OUTPUT.PUT_LINE(B); -- displays the results b
DBMS_OUTPUT.PUT_LINE(C); -- and c
END;
Sorry for the long post.
HOPE THIS HELPS.
CHEERS
Your first block is anonymous block in which you declare procedure - you can call procedure Get_manager_details within anonymous block only. You can't call Get_manager_details from Test_Procedure because there is no such procedure. You need to create your procedure Get_manager_details first
Create or replace procedure Get_manager_details ....
Then you can run
Create or replace procedure Test_Procedure ....
Or it will not compile.
If you are trying to call the procedure get_manager_details inside test_procedure then you first need to create the test procedure.
Add create or replace procedure test_procedure .
Then after creating the test_procedure you can execute it in an anonymous block which will call the get_manager_details procedure.

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.

Stored Procedure Related

I am creating a stored procedure in oracle that is selecting records from login table -
create or replace procedure login_info
(username IN varchar2, password IN varchar2, result OUT number)
as
begin
select * from login;
end;
Whenever I am going to compile this it shows an error:
PLS-00428: an INTO clause is expected in this SELECT statement
What does this mean? I do not understand this.
You have to store the result of your SELECT statement into a variable, you can use sys_refcursor to display the result.
create or replace procedure login_info
(username IN varchar2, password IN varchar2, result OUT number, result_out OUT SYS_REFCURSOR)
as
l_query varchar2(1000) := Null;
begin
l_query := 'select * from login';
open result_out
for l_query;
end;
above code will give you the output
PLS-00428: an INTO clause is expected in this SELECT statement
That means you need an INTO close when you issue bare SELECT from PL/SQL.
:D
More constructively: where do you think the result of your select would go in that code fragment?
create or replace procedure login_info
(username IN varchar2, password IN varchar2, result OUT number)
as
begin
select * from login;
end;
You have to retrieve it somehow in order to be processed by your PL/SQL code. Assuming you have several rows to collect, you should use BULK COLLECT INTO:
create or replace procedure login_info
(username IN varchar2, password IN varchar2, result OUT number)
as
type my_tbl_type IS TABLE OF login%ROWTYPE;
my_tbl my_tbl_type;
begin
select * BULK COLLECT INTO my_tbl from login;
-- do whatever you
-- need here
-- on `my_tbl`.
end;
As a final note, maybe are you looking for an explicit CURSOR instead? You should definitively take a look at PL/SQL 101: Working with Cursors. This is an interesting discussion both about SELECT ... INTO ... and CURSOR manipulation.

Calling a stored PROCEDURE in Toad

I have a defined a new stored procedure but get a error while calling it,
CREATE OR REPLACE PROCEDURE SCOTT.getempsal(
p_emp_id IN NUMBER,
p_emp_month IN CHAR,
p_emp_sal OUT INTEGER)
AS
BEGIN
SELECT EMP_SAL
INTO p_emp_sal
FROM EMPLOYEE_SAL
WHERE EMP_ID = p_emp_id
AND EMP_MONTH = p_emp_month;
END getempsal;
And trying to call it:
getempsal(1,'JAN',OUT) --Invalid sql statement.
Your procedure contains an out parameter, so you need to call it in block like:
declare
a number;
begin
getempsal(1,'JAN',a);
dbms_output.put_line(a);
end;
A simple procedure (let's say with a number parameter) can be called with
exec proc(1);
or
begin
proc(1);
end;
Just write EXECUTE procedure_name('provide_the_valueof_IN parameter','value of in parameter', :k) ;
Run this statement a popup will come set the parameters as in out and the datatype too. U will see the output in another popup window.

Resources