I am trying to create a new package, but I get the ORA-24344: success with compilation error and I cannot figure out what is the problem.
Here is my code:
CREATE OR REPLACE PACKAGE BODY lucratori_pack AS
CURSOR disp_lucrator RETURN LucratorRecType IS
SELECT ID_LUCRATOR, NUME_LUCRATOR, PRENUME_LUCRATOR, SALARIUL FROM LUCRATORI ORDER BY SALARIUL;
PROCEDURE increase_sal(
emp_id LUCRATORI.ID_LUCRATOR%type,
emp_inc_sal LUCRATORI.SALARIUL%type
)
IS
emp_new_sal LUCRATORI.SALARIUL%type;
BEGIN
UPDATE LUCRATORI
SET SALARIUL = SALARIUL + emp_inc_sal
WHERE LUCRATORI.id_lucrator = emp_id
returning SALARIUL INTO emp_new_sal;
END increase_sal;
PROCEDURE getAllEmps
IS
CURSOR c is
SELECT NUME_LUCRATOR, PRENUME_LUCRATOR FROM LUCRATORI;
c_nume LUCRATORI.NUME_LUCRATOR%type;
c_prenume LUCRATORI.PRENUME_LUCRATOR%type;
BEGIN
open c;
loop
EXIT WHEN c%NOTFOUND;
fetch c INTO c_nume, c_prenume;
dbms_output.put_line('Numele: ' || c_nume || ' Prenumele: ' || c_prenume);
end loop;
close c;
END getAllEmps;
END lucratori_pack;
I have tested the procedures, and they do not contain errors. Below is the code for the table I am using in the 2 procedures declared inside the package:
CREATE TABLE Lucratori (
id_lucrator varchar2(5) constraint pk_lucrator primary key,
nume_lucrator varchar2(30),
prenume_lucrator varchar2(30),
data_nasterii date,
salariul number(5),
pozitia_ocupata varchar2(40),
id_companie varchar2(5),
constraint fk_lucrator_companie foreign key (id_companie)
references Companii(id_companie)
);
Firstly, it's the wrong place for a cursor definition, the place just after PACKAGE BODY definition , where some global parameters may be defined. And, that cursor (disp_lucrator) is used nowhere. Then Just remove that :
CREATE OR REPLACE PACKAGE lucratori_pack AS
PROCEDURE increase_sal(emp_id LUCRATORI.ID_LUCRATOR%type,
emp_inc_sal LUCRATORI.SALARIUL%type);
PROCEDURE getAllEmps;
END lucratori_pack;
/
CREATE OR REPLACE PACKAGE BODY lucratori_pack AS
/* CURSOR disp_lucrator RETURN LucratorRecType IS
SELECT ID_LUCRATOR, NUME_LUCRATOR, PRENUME_LUCRATOR, SALARIUL FROM LUCRATORI ORDER BY SALARIUL;*/
PROCEDURE increase_sal(
emp_id LUCRATORI.ID_LUCRATOR%type,
emp_inc_sal LUCRATORI.SALARIUL%type
)
IS
emp_new_sal LUCRATORI.SALARIUL%type;
BEGIN
UPDATE LUCRATORI
SET SALARIUL = SALARIUL + emp_inc_sal
WHERE LUCRATORI.id_lucrator = emp_id
returning SALARIUL INTO emp_new_sal;
END increase_sal;
PROCEDURE getAllEmps
IS
CURSOR c is
SELECT NUME_LUCRATOR, PRENUME_LUCRATOR FROM LUCRATORI;
c_nume LUCRATORI.NUME_LUCRATOR%type;
c_prenume LUCRATORI.PRENUME_LUCRATOR%type;
BEGIN
open c;
loop
EXIT WHEN c%NOTFOUND;
fetch c INTO c_nume, c_prenume;
dbms_output.put_line('Numele: ' || c_nume || ' Prenumele: ' || c_prenume);
end loop;
close c;
END getAllEmps;
END lucratori_pack;
/
Related
I got a pl/sql error when I try to run this package. How can I solve this?
CREATE OR REPLACE PACKAGE pkg_ref_value
IS
ref_value orders.total_order%TYPE;
PROCEDURE proc_display_firstname( cust_id IN customer.customer_id%TYPE);
PROCEDURE proc_ref_value(orderId IN orders.order_id%TYPE);
END pkg_ref_value;
PROCEDURE proc_display_firstname( cust_id IN customer.customer_id%TYPE)
IS
cust_last_name VARCHAR2(20);
CURSOR c1(cust_id customer.customer_id%TYPE ) IS
SELECT UPPER(CONCAT(CONCAT(cust_first_name,' '),cust_last_name)) FROM customer WHERE
customer_id=cust_id;
BEGIN
OPEN c1(cust_id);
LOOP
FETCH c1 INTO cust_last_name;
EXIT
WHEN c1%NOTFOUND
DBMS_OUTPUT.PUT_LINE(cust_last_name);// this is the place I got error
END LOOP;
CLOSE c1;
EXCEPTION
WHEN NO_DATA_FOUND THEN
DBMS_OUTPUT.PUT_LINE('NO DATA FOUND' );
END proc_display_firstname;
PROCEDURE proc_ref_value(orderId IN orders.order_id%TYPE)
IS
or_status orders.order_id%TYPE;
total orders.total_order%TYPE;
v_order_id orders.order_id%TYPE :=orders_id;
CURSOR c2 (orderId orders.order_id%TYPE) IS
SELECT
CASE
WHEN order_status='refunded' THEN total_order*0.25
WHEN order_status='completed' THEN total_order* 0
WHEN order_status='cancelled' THEN total_order*0
END
FROM orders;
BEGIN
v_cust_last_name :=proc_display_firstname(v_order_id);
SELECT order_id,order_status, total_order INTO v_order_id,or_status,total
FROM orders
WHERE order_id = v_order_id;
OPEN c2(orderId);
LOOP
FETCH c2 INTO ref_value;
EXIT WHEN c2%NOTFOUND;
DBMS_OUTPUT.PUT_LINE(ref_value);
END LOOP;
CLOSE c2;
DBMS_OUTPUT.PUT_LINE('cust name:'||v_cust_last_name||' Order Id'||v_order_id||'Order Status'||or_status||'Refund Value'||ref_value);
END proc_ref_value;
END pkg_ref_value;'
There are a few problems here:
You have the statement to create the package spec (CREATE OR REPLACE PACKAGE) but you missed the statement required to create the package body (CREATE OR REPLACE PACKAGE BODY).
You're missing a semi-colon after EXIT WHEN c1%NOTFOUND.
In v_order_id orders.order_id%TYPE :=orders_id;, there is no variable named orders_id which is in scope. I suspect you meant orderId.
The updated package code is shown below:
CREATE OR REPLACE PACKAGE pkg_ref_value IS
ref_value orders.total_order%TYPE;
PROCEDURE proc_display_firstname( cust_id IN customer.customer_id%TYPE);
PROCEDURE proc_ref_value(orderId IN orders.order_id%TYPE);
END pkg_ref_value;
CREATE OR REPLACE PACKAGE BODY pkg_ref_value IS -- add
PROCEDURE proc_display_firstname( cust_id IN customer.customer_id%TYPE) IS
cust_last_name VARCHAR2(20);
CURSOR c1(cust_id customer.customer_id%TYPE ) IS
SELECT UPPER(CONCAT(CONCAT(cust_first_name,' '),cust_last_name))
FROM customer
WHERE customer_id=cust_id;
BEGIN
OPEN c1(cust_id);
LOOP
FETCH c1 INTO cust_last_name;
EXIT WHEN c1%NOTFOUND; -- add ;
DBMS_OUTPUT.PUT_LINE(cust_last_name); -- this is the place I got error
END LOOP;
CLOSE c1;
EXCEPTION
WHEN NO_DATA_FOUND THEN
DBMS_OUTPUT.PUT_LINE('NO DATA FOUND' );
END proc_display_firstname;
PROCEDURE proc_ref_value(orderId IN orders.order_id%TYPE) IS
or_status orders.order_id%TYPE;
total orders.total_order%TYPE;
v_order_id orders.order_id%TYPE := orderId; -- changed from := orders_id
CURSOR c2 (orderId orders.order_id%TYPE) IS
SELECT CASE
WHEN order_status='refunded' THEN total_order*0.25
WHEN order_status='completed' THEN total_order* 0
WHEN order_status='cancelled' THEN total_order*0
END
FROM orders;
BEGIN
v_cust_last_name := proc_display_firstname(v_order_id);
SELECT order_id,order_status, total_order
INTO v_order_id,or_status,total
FROM orders
WHERE order_id = v_order_id;
OPEN c2(orderId);
LOOP
FETCH c2 INTO ref_value;
EXIT WHEN c2%NOTFOUND;
DBMS_OUTPUT.PUT_LINE(ref_value);
END LOOP;
CLOSE c2;
DBMS_OUTPUT.PUT_LINE('cust name:' || v_cust_last_name ||
' Order Id' || v_order_id ||
' Order Status' || or_status ||
' Refund Value' || ref_value);
END proc_ref_value;
END pkg_ref_value;
Im a learning plsql and im trying to create procedure and calling procedure inside another procedure and i can get desired output. But when i tried to create procedure inside another procedure instead of calling another procedure, im getting the below error
"23/1 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 << 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.
23/18 PLS-00103: Encountered the symbol "." when expecting one of the following: in out ... long double ref char time timestamp interval date binary national character nchar
Errors: check compiler log
"
CREATE OR REPLACE PROCEDURE pro (
empn NUMBER,
emp OUT emp5%rowtype
) IS
salar number;
BEGIN
SELECT
a.*
INTO emp
FROM
emp5 a
WHERE
a.empno = empn;
dbms_output.put_line('The hire date is'
|| ' '
|| emp.hiredate);
dbms_output.put_line('Name is'
|| ' '
|| emp.ename);
procedure p44(emp.hiredate in date,emp.ename varchar,sal out number) IS
salar NUMBER;
BEGIN
SELECT
e.sal
INTO salar
FROM
emp5 e
WHERE
e.hiredate = hire
AND e.ename = enamee;
dbms_output.put_line('salary of the employee'
|| ' '
|| enamee
|| 'is '
|| salar);
END p43;
/
If i give empno number as input to procedure pro, i need output with employees hiredate,employee's name and employee's salary like the below one
The hire date is 20-FEB-81
Name is ALLEN
salary of the employee ALLEN is 1600
A procedure is a single program unit with the structure of:
create or replace procedure p43 () is
...
begin
…
end;
/
Your code has two instances of PROCEDURE and that's what the compiler is complaining about.
If you want two separate procedures you need two separate CREATE statements:
create or replace procedure p43 () is
...
begin
…
end p43;
/
create or replace procedure p44 () is
...
begin
…
end p44;
/
But if what you want is P44 as a private procedure only accessible within the context of P43 you can do that, by defining the procedure in the declaration section after any variable declarations:
create or replace procedure p43 () is
…
procedure p44 () is
...
begin
…
end p44;
begin
…
p44(…);
end p43;
/
Also this is not how we declare parameters.
procedure p44(emp.hiredate in date,emp.ename varchar,sal out number) IS
Give them unique names, say by prefixing them with p_, and if you like use the table column datatype. Something like this:
procedure p44(p_hiredate in emp.hiredate%type
,p_ename in emp.ename%type
,p_sal out emp.sal%type) IS
Giving parameters a distinct name prevents scope confusion when using parameters in SQL statements:
You can not create procedure within procedure.
Procedure is a single object and must be created alone. You can call one procedure from another.
You can use package to create multiple procedures inside single package but in that case also, procedure must be created standalone.
-- procedure must be created standalone
Create or replace procedure p44
As
Begin
-- code
End p44;
/
Create or replace procedure pro
As
Begin
P44; -- call to existing procedure
-- code
End pro;
/
So your case will go like this:
procedure p44(hiredate in date,ename varchar,sal out number) IS
salar NUMBER;
BEGIN
SELECT
e.sal
INTO salar
FROM
emp5 e
WHERE
e.hiredate = hire
AND e.ename = ename;
dbms_output.put_line('salary of the employee'
|| ' '
|| ename
|| 'is '
|| salar);
END p44;
/
CREATE OR REPLACE PROCEDURE pro (
empn NUMBER,
emp OUT emp5%rowtype
) IS
salar number;
BEGIN
SELECT
a.*
INTO emp
FROM
emp5 a
WHERE
a.empno = empn;
dbms_output.put_line('The hire date is'
|| ' '
|| emp.hiredate);
dbms_output.put_line('Name is'
|| ' '
|| emp.ename);
P44(emp.hiredate, emp.ename, salr):
END pro;
/
Cheers!!
I am writing a function and i want to wrap it with table function so i can use with select query.
Here is my type declaration and the some lines of my functions
CREATE OR REPLACE PACKAGE TYPES
AS
TYPE CURSORTYPE IS REF CURSOR;
TYPE vbugsrec
IS
RECORD (
bug_id bugs.bug_id%TYPE,
facility bugs.facility%TYPE
);
TYPE vbugstable
IS
TABLE OF vbugsrec
INDEX BY BINARY_INTEGER;
END;
/
CREATE OR REPLACE PACKAGE BODY CustomQueries
AS
FUNCTION pendverifylist (myldapid IN userpass.ldapalias%TYPE,
maxrows IN PLS_INTEGER:= CustomQueries.maxrecords)
RETURN types.vbugstable
IS
datarows types.vbugstable;
var_useralias userpass.ldapalias%TYPE
:= UPPER (pendverifylist.myldapid) ;
CURSOR pendverify_cur (
cursor_var_alias IN userpass.ldapalias%TYPE,
cursor_var_mybugstatus IN bugs.bug_status%TYPE,
cursor_var_wild IN qa_list.component%TYPE
)
IS
SELECT buglist.bug_id, buglist.facility
FROM bugs buglist,
(SELECT qa.product, qa.component
FROM qa_list qa, userpass UP
WHERE qa.qa_id = UP.userid
AND UP.ldapalias = cursor_var_alias) plist
WHERE buglist.bug_status = cursor_var_mybugstatus
AND buglist.smr_state IN (SELECT fs.finalstate
FROM finalstates fs)
AND buglist.facility = plist.product
AND (buglist.product LIKE plist.component
OR plist.component = cursor_var_wild);
BEGIN
OPEN pendverifylist.pendverify_cur (cursor_var_alias => pendverifylist.var_useralias,
cursor_var_mybugstatus => CustomQueries.default_bugstatus,
cursor_var_wild => CustomQueries.wildcard);
FETCH pendverifylist.pendverify_cur
BULK COLLECT INTO pendverifylist.datarows
LIMIT LEAST (GREATEST (0, pendverifylist.maxrows),
CustomQueries.MAXRECORDS);
CLOSE pendverifylist.pendverify_cur;
RETURN pendverifylist.datarows;
END pendverifylist;
END CustomQueries;
/
When i want to use TABLE function like below, i get error.ORA-00902: invalid datatype
SELECT * FROM TABLE(CUSTOMQUERIES.PENDVERIFYLIST ( 'product', 50 ));
Can anyone please help what i am doing wrong here?
Thanks in advance
You're trying to use package-level types in plain SQL, which isn't allowed. The types declared in the package are not visible to or valid outside PL/SQL (or even in plain SQL statements within PL/SQL). A cut-down version of what you're doing:
create or replace package types as
type my_rec_type is record (dummy dual.dummy%type);
type my_table_type is table of my_rec_type index by binary_integer;
end types;
/
create or replace package p42 as
function get_table return types.my_table_type;
end p42;
/
create or replace package body p42 as
function get_table return types.my_table_type is
my_table types.my_table_type;
begin
select * bulk collect into my_table from dual;
return my_table;
end get_table;
end p42;
/
select * from table(p42.get_table);
SQL Error: ORA-00902: invalid datatype
Even within the package, if you had a procedure that tried to use the table function it would error. If you added:
procedure test_proc is
begin
for r in (select * from table(get_table)) loop
null;
end loop;
end test_proc;
... the package body compilation would fail with ORA-22905: cannot access rows from a non-nested table item.
You need to declare the types at schema level, not in a package, so using the SQL create type command:
create type my_obj_type is object (dummy varchar2(1));
/
create type my_table_type is table of my_obj_type;
/
create or replace package p42 as
function get_table return my_table_type;
end p42;
/
create or replace package body p42 as
function get_table return my_table_type is
my_table my_table_type;
begin
select my_obj_type(dummy) bulk collect into my_table from dual;
return my_table;
end get_table;
end p42;
/
select * from table(p42.get_table);
DUMMY
-----
X
Actually tehere is not need to have types in schema level. All you need to do is to define function as PIPELINED.
-- DEFINITION IN PCKG HEADER
create or replace PACKAGE "AAA" IS
TYPE t_record IS RECORD (
aaa VARCHAR(20 CHAR),
bbb VARCHAR(50 CHAR),
ccc VARCHAR(10 CHAR)
);
TYPE t_collection is table of t_record;
FUNCTION get_records(p_in1 DATE, p_in2 DATE) RETURN t_collection PIPELINED;
END AAA;
-- PCKG BODY
create or replace PACKAGE BODY AAA AS
FUNCTION get_records(p_in1 DATE, p_in2 DATE) RETURN t_collection PIPELINED AS
CURSOR k1 is SELECT aaa,bbb,ccc FROM table;
BEGIN
FOR rec IN k1
LOOP
pipe row( (rec) );
END LOOP;
END get_records
END AAA;
-- CALLING FUNCTION OUTSIDE OF PCKG
select * from TABLE(AAA.get_records(par1, par2));
Thanks to Alex Poole. This is what i ended up with
CREATE OR REPLACE TYPE vbugsrec
IS
OBJECT (
bug_id NUMBER(9),
facility VARCHAR2(256)
);
CREATE OR REPLACE TYPE vbugstable
IS
TABLE OF vbugsrec;
/
CREATE OR REPLACE PACKAGE BODY CustomQueries
AS
FUNCTION pendverifylist (myldapid IN userpass.ldapalias%TYPE,
maxrows IN PLS_INTEGER:= CustomQueries.maxrecords)
RETURN vbugstable
IS
datarows vbugstable := vbugstable();
var_useralias userpass.ldapalias%TYPE:= UPPER (pendverifylist.myldapid) ;
TYPE temp_rec IS RECORD (
bug_id bugs.bug_id%TYPE,
facility bugs.facility%TYPE
);
TYPE temp_records
IS
TABLE OF temp_rec
INDEX BY BINARY_INTEGER;
temporary_records temp_records;
CURSOR pendverify_cur (
cursor_var_alias IN userpass.ldapalias%TYPE,
cursor_var_mybugstatus IN bugs.bug_status%TYPE,
cursor_var_wild IN qa_list.component%TYPE
)
IS
SELECT buglist.bug_id, buglist.facility
FROM bugs buglist,
(SELECT qa.product, qa.component
FROM qa_list qa, userpass UP
WHERE qa.qa_id = UP.userid
AND UP.ldapalias = cursor_var_alias) plist
WHERE buglist.bug_status = cursor_var_mybugstatus
AND buglist.smr_state IN (SELECT fs.finalstate
FROM finalstates fs)
AND buglist.facility = plist.product
AND (buglist.product LIKE plist.component
OR plist.component = cursor_var_wild);
BEGIN
OPEN pendverifylist.pendverify_cur (cursor_var_alias => pendverifylist.var_useralias,
cursor_var_mybugstatus => CustomQueries.default_bugstatus,
cursor_var_wild => CustomQueries.wildcard);
FETCH pendverifylist.pendverify_cur
BULK COLLECT INTO temporary_records
LIMIT LEAST (GREATEST (0, pendverifylist.maxrows),
CustomQueries.MAXRECORDS);
CLOSE pendverifylist.pendverify_cur;
IF temporary_records.COUNT <> 0
THEN
FOR rec_idx IN temporary_records.FIRST .. temporary_records.LAST
LOOP
datarows.EXTEND;
datarows (datarows.LAST) :=
vbugsrec (temporary_records (rec_idx).bug_id,
temporary_records (rec_idx).facility);
END LOOP;
END IF;
RETURN pendverifylist.datarows;
END pendverifylist;
END CustomQueries;
/
Here is my code: Quite Straight forward..
create or replace package types
as
type rec is record
(
employee_id NUMBER,
fname varchar2(20)
);
type tab_rec is table of rec;
type tab_numbers is table of number;
type tab_chars is table of varchar2(10);
end types;
/
create or replace
function get_employees_rec
(
O_error_msg IN OUT varchar2,
L_access_tab OUT types.tab_chars
)
return boolean
as
--o_access_tab types.tab_chars;
cursor c_rec is
select first_name from employees;
begin
open c_rec;
fetch c_rec bulk collect into L_access_tab;
close c_rec;
return true;
exception
when others then
O_error_msg:=substr(sqlerrm,1,100);
return false;
end;
/
declare
O_error_msg varchar2(100);
L_access types.tab_chars;
begin
if get_employees_rec(O_error_msg,L_access)=FALSE then
dbms_output.put_line('Got you');
end if;
for rec in(select * from employees e,TABLE(L_access) f where value(f)=e.first_name)
loop
dbms_output.put_line(rec.first_name);
end loop;
end;
/
However I am getting the error :
ORA-21700: object does not exist or is marked for delete
ORA-06512: at line 9
21700. 00000 - "object does not exist or is marked for delete"
*Cause: User attempted to perform an inappropriate operation to
an object that is non-existent or marked for delete.
Operations such as pinning, deleting and updating cannot be
applied to an object that is non-existent or marked for delete.
*Action: User needs to re-initialize the reference to reference an
existent object or the user needs to unmark the object.
What is the reason behind this error?
You can't access those types from an external package like that, rather create them as database objects:
create or replace type rec is object (
employee_id NUMBER,
fname varchar2(20));
create or replace type tab_rec is table of rec;
etc.
I'd like to know how can I return multiple values with my PL/SQL in record type.
Below is my example code :-
CREATE OR REPLACE FUNCTION "FN_TESTING"
(
TESTING1 IN VARCHAR2
) RETURN TEST4_TEST as
TEST2 TEST4_TEST%ROWTYPE;
CURSOR TEST1 IS
SELECT '1','2' FROM DUAL;
BEGIN
OPEN TEST1;
FETCH TEST1
INTO TEST2;
CLOSE TEST1;
RETURN TEST2;
END FN_TESTING;
I do check my function, it shows me warning message that my TEST4_TEST must be declared.
Can I know what is the problem of this function? and how I do the declaration for this TEST4_TEST?
Yes we can return the record variable from PLSQL Function/Procedure. But first it must be declare.
create or replace function get_employee
(p_empl_no in employee.empl_no%type)
return employee%rowtype
as
l_cust_record employee%rowtype;
begin
select * into l_cust_record from employee
where empl_no = p_empl_no;
return(l_cust_record);
end;
/
Think TEST4_TEST as a variable which is of TYPE Record. This variable is just like NUMBER, VARCHAR, DATE. Only difference being that these are already defined by Oracle but in case of Collections and Records we have to define our own.
As per your example it seems that you want to return a record with 2 numbers values then you should define as follow
CREATE OR REPLACE PACKAGE TEST4_TEST1
AS
TYPE TEST4_TEST Is record
(
COL1 INTEGER,
COL2 INTEGER
);
END;
CREATE OR REPLACE FUNCTION FN_TESTING (testing1 IN VARCHAR2)
RETURN TEST4_TEST1.test4_test
AS
test3 TEST4_TEST1.test4_test;
CURSOR test2
IS
SELECT '1', '2' FROM DUAL;
A
BEGIN
OPEN test2;
FETCH test2 INTO test3;
CLOSE test2;
RETURN test3;
END fn_testing;
Try this also:
declare TYPE t_deptrec IS RECORD
(
name dept.dname%type,
location dept.loc%type
);
CURSOR c_emp is
select ename,deptno from emp;
r_dept t_deptrec;
function getDept(p_deptno dept.deptno%type) return t_deptrec is
r_dept t_deptrec;
begin
select dname,loc into r_dept
from dept where deptno = p_deptno;
return r_dept;
end;
BEGIN
for r_emp in c_emp
loop
r_dept := getDept(r_emp.deptno);
dbms_output.put_line(r_emp.ename || ',' || r_dept.name || ',' || r_dept.location);
end loop;
END;