Package "set serveroutput on" causing compilation error - oracle

I'm using my class package template to gather two procedures into the package and after pasting and formatting everything, I came up with this error:
This is my package code. It's separated between head and body.
CREATE OR REPLACE
PACKAGE PAQEX AS
PROCEDURE EX3 (P_NOMBRE IN VARCHAR2, P_LUGAR IN VARCHAR2, P_NUMERO IN NUMBER);
PROCEDURE EX2(CPN IN VARCHAR2, NUMER OUT NUMBER );
END PAQEX;
CREATE OR REPLACE
PACKAGE BODY PAQEX AS
PROCEDURE EX3 (P_NOMBRE IN VARCHAR2, P_LUGAR IN VARCHAR2, P_NUMERO IN NUMBER) AS
--
V_AEROPUERTO NUMBER;
V_TERMINAL NUMBER;
V_ID_AEROPUERTO AEROPUERTO.ID%TYPE;
BEGIN
-----------
SELECT COUNT(*) INTO V_AEROPUERTO FROM AEROPUERTO WHERE NOMBRE = P_NOMBRE AND LUGAR = P_LUGAR;
IF V_AEROPUERTO = 0 THEN
INSERT INTO AEROPUERTO (NOMBRE, LUGAR) VALUES (P_NOMBRE, P_LUGAR);
DBMS_OUTPUT.PUT_LINE('INSERTANDO AEROPUERTO');
ELSE
DBMS_OUTPUT.PUT_LINE('YA EXISTE EL AEROPUERTO');
END IF;
SELECT ID INTO V_ID_AEROPUERTO FROM AEROPUERTO WHERE NOMBRE = P_NOMBRE AND LUGAR = P_LUGAR;
------------
SELECT COUNT(*) INTO V_TERMINAL FROM TERMINAL WHERE NUMERO = P_NUMERO AND ID_AEROPUERTO = V_ID_AEROPUERTO;
IF V_TERMINAL = 0 THEN
INSERT INTO TERMINAL (NUMERO, ID_AEROPUERTO) VALUES (P_NUMERO, V_ID_AEROPUERTO);
DBMS_OUTPUT.PUT_LINE('INSERTANDO TERMINAL');
ELSE
DBMS_OUTPUT.PUT_LINE('YA EXISTE LA TERMINAL');
END IF;
END EX3;
PROCEDURE EX2(CPN IN VARCHAR2, NUMER OUT NUMBER ) AS
CURSOR CVUELO IS
SELECT CS.NOMBRE AS COMPA,MDEL.NOMBRE AS MODELL,ASA.NOMBRE AS ORIGEN,AL.NOMBRE AS DESTINO
FROM VUELO VU
INNER JOIN AVION AVI
ON VU.ID_AVION = AVI.ID
INNER JOIN COMPAÑIA CS
ON AVI.ID_COMPAÑIA = CS.ID
INNER JOIN MODELO MDEL
ON AVI.ID_MODELO = MDEL.ID
INNER JOIN PUERTA PS
ON VU.id_puerta_salida = PS.ID
INNER JOIN PUERTA PL
ON VU.id_puerta_llegada = PL.ID
INNER JOIN TERMINAL TS
ON PS.ID_TERMINAL = TS.ID
INNER JOIN TERMINAL TL
ON PL.ID_TERMINAL = TL.ID
INNER JOIN AEROPUERTO ASA
ON TL.ID_AEROPUERTO = ASA.ID
INNER JOIN AEROPUERTO AL
ON TS.ID_AEROPUERTO = AL.ID
WHERE CPN = CS.NOMBRE;
BEGIN
NUMER:=0;
FOR RESULTADO IN CVUELO
LOOP
DBMS_OUTPUT.PUT_LINE(RESULTADO.COMPA || ' | ' || RESULTADO.MODELL ||' | ' ||RESULTADO.ORIGEN||' | ' ||RESULTADO.DESTINO);
NUMER := NUMER + 1;
END LOOP;
DBMS_OUTPUT.PUT_LINE('La compañia ha volado '||numer||' veces');
END EX2;
END PAQEX;
SET SERVEROUTPUT ON;
EXECUTE PAQEX.EX2('AIRBUS',0);
EXECUTE PAQEX.EX3('ADOLFOS','MADRID',3);
I want try each procedure in the package after creating it. They work as stand-alone procedures but not in the package because of that error. Why does it not accept the set serveroutput on command?

There are two ways you could be creating this package; either from a worksheet with all of the code in one script, in which case it should look something like:
CREATE OR REPLACE
PACKAGE PAQEX AS
PROCEDURE EX3 (P_NOMBRE IN VARCHAR2, P_LUGAR IN VARCHAR2, P_NUMERO IN NUMBER);
PROCEDURE EX2(CPN IN VARCHAR2, NUMER OUT NUMBER );
END PAQEX;
/
CREATE OR REPLACE
PACKAGE BODY PAQEX AS
...
END PAQEX;
/
SET SERVEROUTPUT ON;
EXECUTE PAQEX.EX2('AIRBUS',0);
EXECUTE PAQEX.EX3('ADOLFOS','MADRID',3);
with a slash after each PL/SQL object (package specification and package body).
Or you could be creating or modifying the package from the 'New Package...' menu command, and putting the specification and body code into the relevant objects. The schema browser will show "PAQEX" under 'Packages', and if you click that you'll see a tab with the package icon and "PAQEX" containing just:
CREATE OR REPLACE
PACKAGE PAQEX AS
PROCEDURE EX3 (P_NOMBRE IN VARCHAR2, P_LUGAR IN VARCHAR2, P_NUMERO IN NUMBER);
PROCEDURE EX2(CPN IN VARCHAR2, NUMER OUT NUMBER );
END PAQEX;
and a "PAQEX Body" under that; and if you click that you'll see another tab with the package icon and "PAQEX Body" containing just the body code. But you seem to have included code for testing it as part of the body:
PACKAGE BODY PAQEX AS
...
END PAQEX;
SET SERVEROUTPUT ON;
EXECUTE PAQEX.EX2('AIRBUS',0);
EXECUTE PAQEX.EX3('ADOLFOS','MADRID',3);
From the error image you included, you are getting the error you showed when you click the compile icon (cogs).
You need to separate out the test code from the package code. Remove the SET and EXECUTE lines from the package body tab so that just has:
PACKAGE BODY PAQEX AS
...
END PAQEX;
That should then compile, if there are no other errors.
Then to test the package, open an SQL Worksheet (right-click on the connection to see that in the contextual menu) and put in just those three statements:
SET SERVEROUTPUT ON;
EXECUTE PAQEX.EX2('AIRBUS',0);
EXECUTE PAQEX.EX3('ADOLFOS','MADRID',3);
and click 'Run as script' or press F5. (If you click 'Run as statement' or press control-enter then it will only run the command that your cursor is currently in.)
The SQL Developer EXECUTE command is just a wrapper an anonymous block, so you could also combine both calls with:
SET SERVEROUTPUT ON;
BEGIN
PAQEX.EX2('AIRBUS',0);
PAQEX.EX3('ADOLFOS','MADRID',3);
END;
/
You can also test using the 'Run' icon (or pressing control-F10) while looking at the package object editor; it's next to the compile (cogs) icon. That lets you pick a procedure/function from the package and set the argument values.
From the image of the error, you have opened the package body from the object list, it's only showing the boand you are clicking If you're now in the package body editor - not a worksheet - and clicking the compile button to get that error, then remove the SET and EXECUTE commands instead.

Terminate the procedure with a slash:
<snip>
END EX2;
END PAQEX;
/ --> this
SET SERVEROUTPUT ON;
EXECUTE PAQEX.EX2('AIRBUS',0);

Related

Fill variable from query in Oracle Package

I want populate variable from query in oracle package.
In package I'm define:
g_my_value number;
g_my_value2 number;
PROCEDURE initialize_par;
In package body:
create or replace PACKAGE BODY my_pkg AS
PROCEDURE initialize_par AS
BEGIN
Select parameter_value into g_my_value from tbl_parameters where name = 'my_value';
Select parameter_value into g_my_value2 from tbl_parameters where name = 'my_value2';
END initialize_par;
Before use variable in other procedure in this package I need call
Exec initialize_par to set value in variable.
Is it good option? Is it possible set value in variable without procedure initialize_par?
You can initialise a package (without a procedure) using a BEGIN/END initialiser block in the procedure body:
CREATE PACKAGE package_name IS
g_my_value number;
g_my_value2 number;
END;
/
CREATE PACKAGE BODY package_name
IS
BEGIN
Select parameter_value
into g_my_value
from tbl_parameters
where name = 'my_value';
Select parameter_value
into g_my_value2
from tbl_parameters
where name = 'my_value2';
END;
/
Given the sample parameters:
CREATE TABLE tbl_parameters (name, parameter_value ) AS
SELECT 'my_value', 42 FROM DUAL UNION ALL
SELECT 'my_value2', 3.141 FROM DUAL;
then:
BEGIN
DBMS_OUTPUT.PUT_LINE(package_name.g_my_value);
DBMS_OUTPUT.PUT_LINE(package_name.g_my_value2);
END;
/
Outputs:
42
3.141
fiddle

PL/SQL Package Cursor with custom return value (like in the procedure)

Is it possible to define a cursor with custom return value (columns from different tables..) ?
For example:
CREATE OR REPLACE PACKAGE pkg
IS
CURSOR emp_cur (id_in IN employees.employee_id%TYPE)
RETURN employees%ROWTYPE;
END;
/
CREATE OR REPLACE PACKAGE BODY pkg
IS
CURSOR emp_cur (id_in IN employees.employee_id%TYPE)
RETURN employees%ROWTYPE
IS
SELECT *
FROM employees
WHERE employee_id = id_in;
END;
/
This works because the employees is a single table.
In the procedure i can define cursor
CURSOR CUR_TEST ....
and the later
TYPE t_cur_test IS TABLE OF CUR_TEST %ROWTYPE INDEX BY BINARY_INTEGER;
var_t_cur_test t_cur_test ;
an it works.
In the package however with
CREATE OR REPLACE PACKAGE TEST
IS
-- Public types
CURSOR CUR_TEST
RETURN CUR_TEST%ROWTYPE;
i am getting -> 1/14 PLS-00304: cannot compile body of 'CUR_TEST' without its specification.
Is there any way to do this ?

Oracle Packages and using a select statement in a public variable

Have been searching for ages to no avail. Part of an assessment it specifies that we must declare a public variable WITHIN a package (so don't try telling me to make it a stand alone function...) that is the number of rows from another table ("SELECT COUNT(*) FROM A2_GUESTS" is the hint)
I can set a public variable easily enough as a static number, however if i try to add the select statement it throws an error.
If I try to assign it in the package body then it also throws an error, if I wrap it within "begin" and "end" it terminates the package body too early.
CREATE OR REPLACE PACKAGE Beachcomber
AS
v_Guest_Count NUMBER := 0;
END Beachcomber;
/
CREATE OR REPLACE PACKAGE BODY Beachcomber IS
SELECT COUNT(*) INTO v_Guest_Count FROM A2_GUESTS; -- doesn't work
v_Guest_Count NUMBER := SELECT COUNT(*) FROM A2_GUESTS; -- doesn't work
BEGIN
v_Guest_Count NUMBER := SELECT COUNT(*) FROM A2_GUESTS;
END; -- doesn't work - ends the package prematurely
END Beachcomber;
the above example are the ways i've been trying (amongst others), not at the same time but individually.
We get given the code to test it: (must not change this testing code)
PROMPT
PROMPT TESTING: Initialisation of the v_Guest_Count variable. Expect 81.
BEGIN
DBMS_OUTPUT.PUT_LINE('v_Guest_Count has been initialised to: '||TO_CHAR(BEACHCOMBER.v_Guest_Count));
END;
any help is greatly appreciated, i found someone asked this here once back in 2015 but the only answer was given as make it a function and they adjusted the testing code so thats less than helpful.
there is more code within the package with procedures and functions:
CREATE OR REPLACE PACKAGE Beachcomber
IS
v_Guest_Count NUMBER := 0;
PROCEDURE ADD_GUEST
(p_guest_name A2_GUESTS.guest_name%TYPE,
p_guest_address A2_GUESTS.guest_address%TYPE);
END Beachcomber;
/
CREATE OR REPLACE PACKAGE BODY Beachcomber IS
BEGIN
SELECT COUNT(*) INTO v_Guest_Count FROM A2_GUESTS;
PROCEDURE ADD_GUEST
(p_guest_name A2_GUESTS.guest_name%TYPE,
p_guest_address A2_GUESTS.guest_address%TYPE)
IS BEGIN
INSERT INTO A2_GUESTS (Guest_ID, Guest_Name, Guest_Address)
VALUES (guest_id_seq.NEXTVAL, p_guest_name, p_guest_address);
v_Guest_Count := v_Guest_Count +1;
END ADD_GUEST;
END Beachcomber;
this will throw:
5/5 PLS-00103: Encountered the symbol "PROCEDURE" when expecting one of the following: ( begin case declare end exception exit for goto if loop mod null pragma raise return select update while with <an identifier> <a double-quoted delimited-identifier> <a bind variable> << continue close current delete fetch lock insert open rollback savepoint set sql execute commit forall merge pipe purge The symbol "declare" was substituted for "PROCEDURE" to continue.
im normally alright with working it out from the error messages but oracle error messages may as well be written in dutch to me :/
We can include initialising code in a package by putting it at the end of the body. It takes the form of a BEGIN block which is terminated by the final END of the package body.
create or replace package BEACHCOMBER is
v_Guest_Count pls_integer;
function get_cnt return number;
end BEACHCOMBER;
/
create or replace package body BEACHCOMBER is
function get_cnt return number
is
begin
return v_Guest_Count;
end get_cnt;
<< init_block >>
begin
select count(*)
into v_Guest_Count
from A2_GUESTS;
end BEACHCOMBER;
/
The code under the label << init_block >> is run the first time the package is invoked. This includes referencing the public variable. This code not run again in the session, unless the package is recompiled, which discards state.
Here is my test script. I have published this as a working demo on Oracle LiveSQL (because DBMS_OUTPUT) but you need a free Oracle account to run it. Check it out
Test set up
drop table A2_GUESTS
/
create table A2_GUESTS (id number);
insert into A2_GUESTS select level from dual connect by level <=23;
create or replace package BEACHCOMBER is
v_Guest_Count pls_integer;
function get_cnt return number;
end BEACHCOMBER;
/
create or replace package body BEACHCOMBER is
function get_cnt return number
is
begin
return v_Guest_Count;
end get_cnt;
begin
select count(*)
into v_Guest_Count
from A2_GUESTS;
end BEACHCOMBER;
/
Here are the tests;
begin
dbms_output.put_line('count = ' || BEACHCOMBER.v_Guest_Count);
end;
/
insert into A2_GUESTS values (42)
/
select BEACHCOMBER.get_cnt
from dual
/
alter package BEACHCOMBER compile body
/
select BEACHCOMBER.get_cnt
from dual
/
You have to set the Package variable in the package body. You need not declare another variable locally in the body.
CREATE OR REPLACE PACKAGE BODY Beachcomber IS
BEGIN
SELECT COUNT(*) INTO v_Guest_Count FROM A2_GUESTS;
END Beachcomber;
/
You may then access that variable in any other PL/SQL block.
SET SERVEROUTPUT ON
BEGIN
DBMS_OUTPUT.PUT_LINE(Beachcomber.v_Guest_Count);
end;
/
0
PL/SQL procedure successfully completed.
EDIT
You should put the queries inside the procedure as you would be calling the procedure externally.
CREATE OR REPLACE PACKAGE BODY beachcomber IS
PROCEDURE add_guest (
p_guest_name a2_guests.guest_name%TYPE,
p_guest_address a2_guests.guest_address%TYPE
)
IS
BEGIN
SELECT COUNT(*)
INTO v_guest_count
FROM a2_guests;
INSERT INTO a2_guests (
guest_id,
guest_name,
guest_address
) VALUES (
guest_id_seq.NEXTVAL,
p_guest_name,
p_guest_address
);
v_guest_count := v_guest_count + 1;
END add_guest;
END beachcomber;
/
EDIT2 : using a main procedure for initialisation.
CREATE OR REPLACE PACKAGE beachcomber IS
v_guest_count NUMBER := 0;
PROCEDURE main;
PROCEDURE add_guest (
p_guest_name a2_guests.guest_name%TYPE,
p_guest_address a2_guests.guest_address%TYPE
);
END beachcomber;
/
CREATE OR REPLACE PACKAGE BODY beachcomber IS
PROCEDURE add_guest (
p_guest_name a2_guests.guest_name%TYPE,
p_guest_address a2_guests.guest_address%TYPE
)
IS
BEGIN
INSERT INTO a2_guests (
guest_id,
guest_name,
guest_address
) VALUES (
guest_id_seq.NEXTVAL,
p_guest_name,
p_guest_address
);
v_guest_count := v_guest_count + 1;
END add_guest;
PROCEDURE main
IS
BEGIN
SELECT COUNT(*)
INTO v_guest_count
FROM a2_guests;
END main;
END beachcomber;
/
Execution of procedure.
BEGIN
beachcomber.main;
beachcomber.add_guest('Sherlock','221b baker street');
END;
/

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.

how to call plsql procedure out parameter as a user-defined ref cursor?

I have a package P and a precedure A in it.
create or replace package pkg_get_users_info_by_role
as
type user_info_ref_cur is ref cursor;
procedure get_user_info_proc
(p_role_name varchar2, p_user_info out user_info_ref_cur);
end pkg_get_users_info_by_role;
/
and the body;
create or replace package body pkg_get_users_info_by_role
as
procedure get_user_info_proc
(p_role_name varchar2, p_user_info out user_info_ref_cur)
as
begin
open p_user_info for
select user_id,username,user_password,role_name from user_info,role_info
where user_info.user_role=role_info.role_id
and role_info.role_name like p_role_name;
end;
end pkg_get_users_info_by_role;
My question is, how can I call the procedure? Do I need a variable of pkg_get_users_info_by_role.user_info_ref_cur type to call it? I cannot create a variable of this type. Is there any way to solve this?
Thanks!!
Yes, you simply define your cursor in your calling program as the package.type. Here's a simple-minded illustration that should work on most any oracle database:
CREATE OR REPLACE PACKAGE pkg AS
TYPE rc IS REF CURSOR;
PROCEDURE get_rc(p_rc OUT rc);
END pkg;
/
CREATE OR REPLACE PACKAGE BODY pkg AS
PROCEDURE get_rc(p_rc OUT rc) IS
BEGIN
OPEN p_rc FOR
SELECT t.owner, t.table_name FROM all_tables t;
END get_rc;
END pkg;
/
DECLARE
crsr pkg.rc;
v1 VARCHAR2(32);
v2 VARCHAR2(32);
BEGIN
pkg.get_rc(crsr);
LOOP
EXIT WHEN crsr%NOTFOUND;
FETCH crsr INTO v1, v2;
dbms_output.put_line(v1||': '||v2);
END LOOP;
CLOSE crsr;
END;
/

Resources