Oracle stored procedure not working PLS-00306 - sql

i have this questions i am trying to solve and find below what i have solved so far. although the stored procedure haveno error but calling it i get this error :
ERROR at line 2: ORA-06550: line 2, column 3: PLS-00306: wrong
number or types of arguments in call to 'PUB_JOB_COUNT' ORA-06550:
line 2, column 3: PL/SQL: Statement ignored
Requirement:
Create a stored PL/SQL procedure object in the database. The procedure
should insert the publisher’s name, city, telephone number and the
number (count) of jobs he/she requested in the table PublisherDetails
for each Publisher who requested less than three print jobs otherwise
the procedure should display on the screen the publisher name followed
by job number, job start date and job completion date for each job
he/she requested. Screen output (hint: use the concatenation operator
‘||’) should be in the following format:
Please someone help me out please?
Publisher Name: Addison-Wesley
JobNo Start Date Completion Date
12 17-JAN-14 25-JAN-14
14 28-FEB-14 01-APR-14
Finally, a NO-DATA-FOUND exception should be catered for in the
EXCEPTION section and a message displayed on the screen (hint: use
DBMS_OUTPUT.put_line procedure provided by Oracle) informing the user
if such an error arises. Note that in order for DBMS_OUTPUT.put_line
to work in SQL*Plus, you should set SERVEROUTPUT on first. You should
check if the procedure executes properly by invoking the procedure and
checking the content of the PublisherDetails table. Do the following:
a) Create a script file with the necessary code to create the table
PublisherDetails and the PL/SQL procedure in the database; b) Create a
second script file with the following: • An SQL statement that clears
the content of the table PublisherDetails; • A PL/SQL anonymous block
statement to invoke (execute) the PL/SQL procedure; • A SELECT
statement to select all the records in PublisherDetails table.
my tables
publisher(publisherName, publisherCity, phoneNo)
pk
printJob(JobNo, startDate, complitionDate, publisherName)
pk fk(publisher)
publisherdetails(publisherName, publisherCity, phoneNo, JobNo)
pk
Code:
CREATE OR REPLACE PROCEDURE PUB_JOB_COUNT (
JOBNO IN NUMBER
) AS
PUBLISHERNAME PRINTJOB.PUBLISHERNAME%TYPE;
NOTFOUND EXCEPTION;
CURSOR PUBCURSOR IS
SELECT PUBLISHER.PUBLISHERNAME,
PUBLISHER.PUBLISHERCITY,
PUBLISHER.PHONENO,
PRINTJOB.STARTDATE,
PRINTJOB.COMPLETIONDATE,
SUM(JOBNO) AS NUMOFJOBS
FROM PUBLISHER
INNER JOIN PRINTJOB ON PUBLISHER.PUBLISHERNAME = PRINTJOB.PUBLISHERNAME
GROUP BY PUBLISHER.PUBLISHERNAME,
PUBLISHER.PUBLISHERCITY,
PUBLISHER.PHONENO,
PRINTJOB.STARTDATE,
PRINTJOB.COMPLETIONDATE;
PUBREC PUBCURSOR%ROWTYPE;
BEGIN
OPEN PUBCURSOR;
FOR PRINTJOB IN PUBCURSOR LOOP
PUBLISHERNAME := PRINTJOB.PUBLISHERNAME;
DBMS_OUTPUT.PUT_LINE('Publisher Name : ' || PRINTJOB.PUBLISHERNAME);
LOOP
FETCH PUBCURSOR INTO PUBREC;
EXIT WHEN PUBCURSOR%NOTFOUND;
IF PUBREC.NUMOFJOBS <= 3 THEN INSERT INTO PUBLISHERDETAILS VALUES (
PUBREC.PUBLISHERNAME,
PUBREC.PUBLISHERCITY,
PUBREC.PHONENO,
PUBREC.NUMOFJOBS
);
ELSE DBMS_OUTPUT.PUT_LINE(PUBREC.NUMOFJOBS
|| ' '
|| PUBREC.STARTDATE
|| ' '
|| PUBREC.COMPLETIONDATE);
END IF;
END LOOP;
END LOOP;
CLOSE PUBCURSOR;
COMMIT;
EXCEPTION
WHEN NOTFOUND THEN DBMS_OUTPUT.PUT_LINE('Record Not Found');
END;
Gleaned from comments below, the code being used to execute the procedure:
BEGIN
pub_Job_Count;
End;

Your program is expecting an input, a number.
But when you call it, you're not providing said number.
So, the database gets upset and issues this:
PLS-00306: wrong number or types of arguments in call to 'PUB_JOB_COUNT'
To fix it,
BEGIN
pub_Job_Count(1); -- your number is added here, either explicitley or via a variable you add in a DECLARE
END;
/
A basic example
clear screen
create or replace procedure so_missing_inputs (x in integer, y in date) is
begin
dbms_output.put_line('X is: ' || x);
dbms_output.put_line('Y is: ' || to_char(y, 'MM-DD-YYYY HH24:MI:SS'));
end;
/
set serveroutput on
declare
a integer := 2;
b date := sysdate;
begin
-- so_missing_inputs(); -- missing 2 inputes
-- so_missing_inputs(1); -- missing 1 inputs
-- so_missing_inputs(sysdate, 2); -- right number of inputs, but not right data types
so_missing_inputs(x => a, y => b); -- let's be explicit about inputs vs coutning on right order
end;
/
If I run this -
If you were to uncomment one of the previous lines, you'd see the PLS-00306 creep back in.
One final note, on DBMS_OUTPUT. It's a good way to see what things are happening while 'debugging' your code, but it's not a good way to communicate things outside the PL/SQL program.

Related

Retrieve data by user input with a message (PL/SQL)

I want to how to retrieve data from the table I have added here by inserting C_Id as the user input with defined variables and exceptions. If any customer is not available it has to display a message showing "No customer found". Please help me to understand this one.
Thank you!
If it is a stored procedure (should be; it accepts a parameter) and you just want to display what you found, then this might be one option:
create or replace procedure p_test (par_c_id in customer_details.c_id%type)
is
l_row customer_details%rowtype;
begin
select *
into l_row
from customer_details
where c_id = par_c_id;
dbms_output.put_line(l_row.customer_name ||', '||
l_row.address ||', '||
to_char(l_row.date_of_joined, 'dd.mm.yyyy')
);
exception
when no_data_found then
dbms_output.put_line('No customer found');
end;
/
Then run it as
set serveroutput on
begin
p_test(121);
end;
/
What does it do?
accepts a parameter
declares local variable which is equal to table's rowtype
select everything into the variable
using dbms_output.put_line, display elements you want
if nothing has been found, exception (no_data_found) is raised and handled in a way that you display appropriate message
Note that such an option works if tool you use (e.g. SQL*Plus, SQL Developer, TOAD, ...) allow displaying result of dbms_output.put_line. Otherwise, if you use e.g. Oracle Apex, procedure will still work, but you won't see anything.

'Cursor is already open' error when I try to execute my procedure in oracle sql

I wrote a function in oracle sql to fetch the name of an employee whose id in the table matches the input given to the function .
create or replace function id_search
(
x in number
)
return number
is
cursor e is select ename from employee where emp_id = x;
begin
open e;
for i in e
loop
dbms_output.put_line('name is :'||i.ename);
end loop;
close e;
return 0;
end;
/
After this , I called this function in a procedure I had written :
SQL> create or replace procedure id_searchP
2 (
3 y in number
4 )
5 is
6 t number:= 1;
7 begin
8 t := id_search(y);
9 end;
10 /
However , when I try to execute my procedure , I am encountering the error :
SQL> exec id_searchP(2);
BEGIN id_searchP(2); END;
*
ERROR at line 1:
ORA-06511: PL/SQL: cursor already open
ORA-06512: at "tom.ID_SEARCH", line 7
ORA-06512: at "tom.ID_SEARCH", line 10
ORA-06512: at "tom.ID_SEARCHP", line 8
ORA-06512: at line 1
why Am I getting this error ?
You are opening and closing the cursor two times. You do not need to open e; and then again for i in e. Do i like this in your function:
create or replace function id_search(x in number)
return number
is
cursor e
is
select ename
from employee
where emp_id = x;
begin
for i in e loop
dbms_output.put_line('name is :'||i.ename);
end loop;
return 0;
end;
Then the procedure is ok:
create or replace procedure id_searchP(y in number)
is
t number:= 1;
begin
t := id_search(y);
end;
And then only one call will be enough:
BEGIN
id_searchP(2);
END;
Here is the DEMO
There are very few times when you need to use an explicitly-declared cursor. Get in the habit of using cursor FOR-loops:
create or replace function id_search(pinEmployee_ID in number)
return number
is
begin
for rowEmployee in (select ename
from employee
where emp_id = pinEmployee_ID)
loop
dbms_output.put_line('name is :' || rowEmployee.ename);
end loop;
return 0;
end id_search;
There - shorter, simpler, less error-prone, and easier to understand.
Please use meaningful names. I don't care if it's a school assignment or whatever - use meaningful names. Don't make people dig into your code to figure out what your parameters mean or are used for.
Further - please take the time to format your code so it's readable. Indent consistently, make sure that code levels are apparent to the naked eye, put whitespace in so your code can be read easily, spell things properly, and spell things out. I don't want to see ifor a parameter name - if what's being passed in is (supposed to be) an employee ID, then make sure that the name of the parameter makes that apparent. Computer programming is primarily an exercise in communication - between you, the computer, and the poor dumb SOB who in ten years will have to read your code and figure out what it does. Don't be the guy that everyone cusses at when they have to maintain your code. Develop good habits now.
Programming is a craft. If this is something you really want to do, work on doing it well. Every assignment, every script, every day is an opportunity to improve. Or at the very least to show what you know. Make sure that what you show is your best, always.
You are encountering this issues because you are explicitly opening cursor e, and then attempting to start a cursor for loop on cursor e. However, the cursor for loop implicitly attempts to open cursor e, which you already explicitly opened.
If you want to use a cursor for loop you will need to remove your explicit open and close statements.

How do I search for records in a table using a procedure in PL/SQL?

I'm trying to...
Ask user for input and store the input to a variable
Pass this variable into a procedure
Procedure then should iterate through every row in one column of a certain table
If the variable matches then all columns for that row will be printed out via. DBMS_OUTPUT.PUT_LINE('');
Procedure continues to iterate through all rows until finished
I've tried reading my course-material, but the procedures being created are for different uses (e.g. updating a column in a row when a 'where' condition is met) and I'm struggling to understand how to use a procedure to do what I'm trying to do.
The table 'Vehicles' has rows 'v_regno'(PK), 'v_make', 'v_model', 'v_year' etc.
Here's the code.
/*Procedure to search for car by make*/
CREATE OR REPLACE PROCEDURE SaleByMake(
search_make IN VARCHAR2(15)
)
IS
BEGIN
FOR /*each row in 'Items' table*/
IF i_make = search_make THEN
/*Print out columns of this row*/
END IF;
END LOOP;
EXCEPTION
WHEN OTHERS THEN /*What goes in here?*/
END;
-- Get Input from User
ACCEPT search_make CHAR(15) PROMPT 'Enter car make: ';
-- Call the SaleByMake() Procedure and check stock amount status of item
EXECUTE SaleByMake(&search_make);
is that what you Need?
/*Procedure to search for car by make*/
CREATE OR REPLACE PROCEDURE SaleByMake(
search_make IN VARCHAR2
)
IS
BEGIN
FOR rec in (select col1,col2,col3 from table where col = search_make )
Loop
DBMS_OUTPUT.PUT_LINE(rec.col1||' ' || rec.col2||' ' ||rec.col3);
END LOOP;
EXCEPTION
WHEN OTHERS THEN /*What goes in here?*/
END;
you should replace the select the table Name a column names with names you need

PL/SQL Exception handling and update statements

I'm quite new to PL/SQL and I have a problem with displaying my exceptions that I can't seem to figure out.
I'm using two stored procedures and an anonymous block to call them. I've made a few other procedures in this manner and they all work just fine.
This is the first procedure that is updating my table.
create or replace procedure UPD_CUST_SALESYTD_IN_DB (pcustid number, pamt number) AS
err_pamt exception;
err_pcustid exception;
vcount number;
begin
select count(*) into vcount from customer where
custid = pcustid;
if vcount = 0 then raise err_pcustid;
end if;
if pamt <-999.99 or pamt >999.99 then raise err_pamt;
end if;
update customer set sales_ytd = sales_ytd + pamt
where custid = pcustid;
exception
when err_pcustid then
RAISE_APPLICATION_ERROR(-20031, 'Customer ID not found');
when err_pamt then
RAISE_APPLICATION_ERROR(-20032, 'Amount out of range');
when others then
RAISE_APPLICATION_ERROR(-20000, SQLERRM);
end;
This is the procedure that calls the above procedure. This is just displaying what I'm going to do and confirms that it worked.
create or replace procedure UPD_CUST_SALESYTD_VIASQLDEV (pcustid number, pamt number) AS
begin
dbms_output.put_line('--------------------------------------------');
dbms_output.put_line('Updating SalesYTD. Customer Id: ' || pcustid || ' Amount: ' || pamt);
UPD_CUST_SALESYTD_IN_DB(pcustid, pamt);
commit;
dbms_output.put_line('Udpate OK');
exception
when others then
RAISE_APPLICATION_ERROR(-20000, SQLERRM);
end;
This is the anonymous block I'm using to call the above procedure which then calls the one above that.
set serveroutput on;
begin
UPD_CUST_SALESYTD_VIASQLDEV(3,999.9);
end;
If I pass parameters that would not give me an error, all the code works just fine.
For example, if I input;
set serveroutput on;
begin
upd_cust_salesytd_viasqldev(3,400);
end;
I get the correct output and the changes have been made in the table.
--------------------------------------------
Updating SalesYTD. Customer Id: 3 Amount: 400
Udpate OK
However, if I pass parameters that would result in an error, either a customer id not existing or the amount being out of the range, nothing happens.
I get this:
--------------------------------------------
Updating SalesYTD. Customer Id: 3 Amount: 1000
Nothing else.
In similar procedures my exceptions are working just fine. This example is using a procedure that inserts into a table.
--------------------------------------------
Adding Customer. ID: 500 Name: Helen Nolan
ORA-20002: Customer ID out of range
I'm not sure why this procedure is not returning my exceptions at all. In my other procedures that work, if an exception is raised, the script output in Oracle SQL Developer just displays my exception.
However, in my update procedure, if something should raise an exception, above the dbms output lines, the script output prints this error report
Error report -
ORA-20000: ORA-20032: Amount out of range
ORA-06512: at "S4931645.UPD_CUST_SALESYTD_VIASQLDEV", line 10
ORA-06512: at line 2
20000. 00000 - "%s"
*Cause: The stored procedure 'raise_application_error'
was called which causes this error to be generated.
*Action: Correct the problem as described in the error message or contact
the application administrator or DBA for more information.
So it's acknowledging there that my exception has been raised, but isn't shown.
Any help is greatly appreciated, I'm thoroughly confused by this. Am I making some truly obvious mistake?
Not an expert here — just helping brainstorm. It sounds like you are getting a response but you just need to write a custom error statement. Out of range means that in the list that was selected with parameters set that it does not exist within the scope of that query. For example if list was 0-100 then response was from 0-10 and 0 was not found in that range.

Oracle Stored Procedure 'Learnings' issue

I have been tasked (as part of an assignment) to write a stored procedure in Oracle PL/SQL. There are 3 requirements that have to be met.
There must be 2 parameters, 1 IN and 1 OUT.
I must use an implicit cursor and SQL function to calculate a count of the numbers of fields of the same type (in this case the type is car models, so how many cars of each model are there).
I must use another implicit cursor to display the description of the models.
To be honest, I am at a loss. So far for the stored proc I have:
CREATE OR REPLACE Procedure model_details_sp
(p_model IN VARCHAR2,
p_noofcars OUT NUMBER)
IS
BEGIN
SELECT COUNT(Model_Name) INTO p_noofcars
FROM i_car
GROUP BY Model_Name;
END;
I really have no idea where to go from here. Any advice or direction would be most appreciated.
Many thanks.
Hi guys I appreciate all the comments. I wasn't very clear with the end requirements. I want to be able to call this procedure via an anonymous block so that the user will enter a model type (&vairalbe) and the procedure will display how many of that model types are in the database.
When dealing with this type of problems, first think about the data you're trying to capture.
Dealing with implicit cursors in PL/SQL require 1-row, so you need to make sure you understand the data.
In this case, you pass in a variable that you don't use in any of your queries, so I suggest you re-evaluate.
I don't have a database at hand to run this, but you should be able to work this out and hopefully get you a bit closer. I put it in an anonymous block so that I can write it really quick.
DECLARE
PROCEDURE model_details_sp (p_model IN VARCHAR2, p_noofcars OUT NUMBER)
IS
p_description VARCHAR2 (200);
BEGIN
--2
SELECT COUNT (model_name)
INTO p_noofcars
FROM i_car
WHERE model_name = p_model;
DBMS_OUTPUT.put_line ('No of Cars for model: ' || p_noofcars);
--3
SELECT model_description
INTO p_description
FROM i_car --the table should be the car_model table so that only one record is returned
WHERE model_name = p_model;
DBMS_OUTPUT.put_line ('Model Desc' || p_description);
END model_details_sp;
BEGIN
dbms_output.put_line('');
END;
To #David Aldridge comment:
Try running this--the result should be a failure--as you cannont select multiple rows using the into CLAUS, unless you aggregate the data:
DECLARE
p_num NUMBER;
BEGIN
SELECT LEVEL INTO p_num FROM DUAL CONNECT BY LEVEL <= 10;
dbms_output.put(p_num);
END;
The error you should see is this:
Error report:
ORA-01422: exact fetch returns more than requested number of rows
ORA-06512: at line 4
01422. 00000 - "exact fetch returns more than requested number of rows"
*Cause: The number specified in exact fetch is less than the rows returned.
*Action: Rewrite the query or change number of rows requested
From the description and subsequent comments, this is the solution I would provide:
DECLARE
PROCEDURE model_details_sp
(p_model IN VARCHAR2,
p_noofcars OUT NUMBER)
IS
BEGIN
SELECT COUNT(*)
INTO p_noofcars
FROM i_car
WHERE model_name = p_model;
END;
no_of_cars NUMBER := 0;
BEGIN
model_details_sp(:model_name, no_of_cars);
dbms_output.put_line('no of cars for ' || :model_name || ' = ' || no_of_cars);
END;
I've created the PROCEDURE in-line but you can just as easily extract this to the database by removing it from the declare section and executing it with CREATE OR REPLACE.
This example assumes use of an IDE that supports bind variable replacement (:model_name) on execute of the anonymous block. In TOAD, for example, the "user" will be prompted to provide a value for :model_name.