Returning a cursor from a procedure - sql

I am trying to return a cursor from a procedure which will display the contents of a table invoice. The package and procedure was successfully created but when I run the line - Exec CursorPckg.CursorTest_Proc(); I get the following error component 'CURSORTEST_PROC' must be declared any ideas? I'm running SQL*PLUS
CREATE or REPLACE PACKAGE CursorPckg
IS
TYPE salary_type IS REF CURSOR RETURN Invoice%ROWTYPE;
END CursorPckg;
CREATE OR REPLACE PACKAGE BODY CursorPckg AS
PROCEDURE CursorTest_Proc (c1 OUT CursorPckg.salary_type)
IS
BEGIN
OPEN c1 FOR
SELECT * FROM Invoice;
END CursorTest_Proc;
END CursorPckg;

You need to add procedure declaration in package declaration for it to be accessible from outside your package.
Like this:
CREATE or REPLACE PACKAGE CursorPckg
IS
TYPE salary_type IS REF CURSOR RETURN Invoice%ROWTYPE;
PROCEDURE CursorTest_Proc (c1 OUT CursorPckg.salary_type);
END CursorPckg;
Edit:
To answer Your comment. You cannot execute this procedure without providing parameter of type CursorPckg.salary_type.

Related

Return of mysql procedure using golang

I'm having a problem getting the return of a procedure using golang. If I remove the parameters from the procedure the procedure is executed normally, however, when I need to get the return (OUT parameter) I can not get it and the procedure is not executed. To make the tests simpler and to get help, I created a simple procedure as below and I want to get the return of it.
Follow procedure below:
drop procedure if exists PESSOA_TESTE;
delimiter $$
create procedure PESSOA_TESTE(out psaida int)
begin
set psaida = 2;
end
$$
Now it follows the section of golang code that I'm using to try to get the value 2 specified in the procedure.
var GerenciaBD GERENCIABD
var PontoExecucao int
GerenciaBD.F_GERENCIABD_ABRIR_CONEXAO_MYSQL()
GerenciaBD.DataBase.ExecContext(context.TODO(),"call PESSOA_TESTE", sql.Named("psaida", sql.Out{Dest:&PontoExecucao}))
println(PontoExecucao)
When executing I have as answer 0 and not 2, which is the one specified in the procedure.
My golang version is at 1.10.
You can see here that usage of out parameter is not yet implemented for https://github.com/go-sql-driver/mysql library.
I'm not sure what you want to do with your code, but if you want to return only one value, you can do something like this:
Stored procedure:
drop procedure if exists PESSOA_TESTE;
delimiter $$
create procedure PESSOA_TESTE(IN psaida int)
begin
SET psaida = 2;
select psaida;
end
$$
Code:
var GerenciaBD GERENCIABD
var PontoExecucao int
GerenciaBD.F_GERENCIABD_ABRIR_CONEXAO_MYSQL()
GerenciaBD.DataBase.QueryRowContext(context.TODO(),"CALL PESSOA_TESTE(?)", PontoExecucao).Scan(&PontoExecucao)
println(PontoExecucao)

Component must be declared error (ORA-06550)

Im getting this error:
ORA-06550:line 1, column 25:PLS-00302: component PA_EXCEPTION_LIST_UPDATE must be declared: line1, column 7:PL/SQL: Statement ignored.
I can't figure out what i did wrong.
PROCEDURE Pa_exception_list_update (p_ceid collection_entities.ceid%TYPE,
p_idusr users.idusr%TYPE
)
IS
v_idusr users.idusr%TYPE;
v_ceid collection_entities.ceid%TYPE;
BEGIN
INSERT INTO pa_exception_list(pa_exception_list_id,
ceid,
creation_date,
created_by)
VALUES(pa_exception_list_seq.nextval, p_ceid, SYSDATE, p_idusr);
END Pa_exception_list_update;
It looks like you are calling the procedure before it has been declared.
Look at this example.
Procedure A calls procedure B. But B is unknown at that moment.
create or replace package test is
begin
end test;
create or replace package body test is
procedure a
is
begin
b;
end;
procedure b is
begin
-- do someting
end;
end test;
Solution. Change the order of the procedures within the package or place the procedure in the package specification.
create or replace package test is
begin
procedure b;
end test;
create or replace package body test is
procedure a
is
begin
b;
end;
procedure b is
begin
-- do someting
end;
end test;
According error message the error appears at line 1.
In case this is a stand-alone procedure you must write like create or replace procedure Pa_exception_list_update ...
In case this is part of a PL/SQL Package then you must write like
CREATE OR REPLACE PACKAGE BODY <package name> AS
procedure Pa_exception_list_update ...
I think you are missing something when you declare.
p_ceid IN collection_entities.ceid%TYPE,
p_idusr IN users.idusr%TYPE
I also faced the same problem.
After checking I found that, the procedure i was calling did not exist in the package!.
Later changed the procedure name and it worked.

Variable must be declared error in a stored procedure

I have a package whose body consists of a stored procedure.
The stored procedure makes a call to a stored procedure in another package. However I need to pass the result of a select statement as a parameter. so I stored the result in a variable and passed it as a parameter. However when the procedure call is performed, it says, the variable is not declared.
This is the sample code.
create or replace
PACKAGE BODY PKG_BODY
PROCEDURE PROC (error OUT VARCHAR2,
RESULT OUT BOOLEAN ) AS
-----------------------------
-----------------------------
DECLARE
PARAM TABLE1.COLUMN1%TYPE;
BEGIN
SELECT COLUMN1
INTO PARAM
FROM TABLE1
WHERE COLUMN2=ID AND COLUMN3='NAME';
END;
PUBLISH_MSG.PUBLISH_PMM_MSG('ID',PARAM,PO_ERR_MSG); --another procedure call
END PROC;
I am getting the following error :
PLS:00201 'Identifier PARAM must be declaed'
Do I have to declare the PARAM before somewhere else? Please help !!
You have defined that variable in a nested PL/SQL block - it can't be accessed from an outer block (it doesn't even exist after the block is finished). You should move definition of your param variable to the outer block, for example:
PROCEDURE PROC (error OUT VARCHAR2,
RESULT OUT BOOLEAN )
AS
PARAM TABLE1.COLUMN1%TYPE;
BEGIN
-----------------------------
-----------------------------
SELECT COLUMN1
INTO PARAM
FROM TABLE1
WHERE COLUMN2=ID AND COLUMN3='NAME';
PUBLISH_MSG.PUBLISH_PMM_MSG('ID',PARAM,PO_ERR_MSG); --another procedure call
END PROC;

Package and Procedure Compilation

Struggling for over an hour now... Why won't this compile?
The Body compiles fine:
create or replace package body "PKG_CUSTOMER" is
PROCEDURE Create_Customer
( pr_customer_id customer.Customer_id%type,
pr_country customer.country%type,
pr_first_name customer.first_name%type,
pr_last_name customer.last_name%type,
pr_birth_date customer.birth_date%type,
pr_customer_type customer.customer_type%type,
pr_address customer.address%type)
IS
BEGIN
INSERT INTO customer (Customer_ID,Country,First_Name,Last_Name,Birth_Date,Customer_Type,Address)
VALUES(pr_customer_id, pr_country, pr_first_name, pr_last_name, pr_birth_date, pr_customer_type, pr_address);
END Create_Customer;
PROCEDURE Delete_Customer(pr_customer_id customer.customer_id%type) IS
BEGIN
DELETE FROM order_line WHERE fk1_order_id IN (SELECT order_id FROM placed_order WHERE fk1_customer_id = pr_customer_id);
DELETE FROM placed_order WHERE fk1_customer_id = pr_customer_id;
DELETE FROM customer WHERE customer_id = pr_customer_id;
END Delete_Customer;
end "PKG_CUSTOMER";​
But the specification won't compile:
create or replace package PKG_CUSTOMER as
Procedure CREATE_CUSTOMER;
Procedure DELETE_CUSTOMER;
end;​
I am getting this error:
Compilation failed,line 3 (21:20:46)
PLS-00323: subprogram or cursor 'CREATE_CUSTOMER' is declared in a package specification and must be defined in the package bodyCompilation failed,line 4 (21:20:46)
PLS-00323: subprogram or cursor 'DELETE_CUSTOMER' is declared in a package specification and must be defined in the package body
I'm using Oracle APEX.
The package specification has to provide the complete specification for the procedures that you want to expose. That includes the parameters. Assuming that you want to make both of the procedures that you declared in the package available to callers outside of the package
create or replace package PKG_CUSTOMER
as
Procedure CREATE_CUSTOMER(
pr_customer_id customer.Customer_id%type,
pr_country customer.country%type,
pr_first_name customer.first_name%type,
pr_last_name customer.last_name%type,
pr_birth_date customer.birth_date%type,
pr_customer_type customer.customer_type%type,
pr_address customer.address%type);
Procedure DELETE_CUSTOMER(pr_customer_id customer.customer_id%type);
end;​
If your intention is to declare a CREATE_CUSTOMER and a DELETE_CUSTOMER procedure that each accept 0 arguments, you would need to implement those procedures in the package body as well.

Dynamic SQL not working as expected

create or replace procedure createtables
Authid current_user as
begin
execute immediate 'create table newcustomer as select * from customer';
end;
create or replace procedure e
is
begin
createtables;
select * from newcustomer;
end;
I got two procedures above. first one will create a new tables called newcustomer, second procedure will call the first procedure and query to the newcustomer table. when I try to compile this code, it says the table is not yet created, I don't really get it as I have called createtables procedure so I assume I have created the table.
Any help will be appreciated. Thanks
Compiling the second procedure without executing the first procedure first will fail, since the table has not been created.
You cannot compile a procedure that relies on objects that do not exist.
Use EXEC createtables before creating procedure e, and do not call createtables in there.
Procedure e will also not compile because you are not using the results of select * from newcustomer as cursor or store the results into variables.
EDIT:
Instead of procedures, you could use an anonymous block. Put the following into a file and execute it (via SQL*Plus for example):
Create Table newcustomer As Select * From customer;
Begin
Null; --# Do something with your new table in here.
End;
/