Implementing and testing a stored PL/SQL procedure - sql

I'm trying to to insert a row into APPLICANT table and to generate a warning whenever a new applicant has the same values of all attributes except applicant number (a#) as an applicant already recorded in a table APPLICANT. Pass the values of attributes through the input parameters of a stored procedure INSAPP.
Here is my code:
CREATE OR REPLACE PROCEDURE INSAPP(
a_num IN NUMBER,
a_fname IN VARCHAR,
a_lname IN VARCHAR,
a_address IN VARCHAR,
a_city IN VARCHAR,
a_state IN VARCHAR,
a_phone IN NUMBER,
a_fax IN NUMBER,
a_email IN VARCHAR,
a_acomment IN LONG) IS
app_row APPLICANT%ROWTYPE;
FAIL EXCEPTION;
BEGIN
--VERIFY APPLICANT FNAME
SELECT *
INTO app_row
FROM APPLICANT
WHERE fname = a_fname AND
lname = a_lname AND
address = a_address AND
city = a_city AND
state = a_state AND
phone# = a_phone AND
fax# = a_fax AND
email = a_email AND
acomment = a_acomment;
EXCEPTION
WHEN NO_DATA_FOUND THEN
DBMS_OUTPUT.PUT_LINE('CREATING APPLICANT');
BEGIN
SELECT MAX(a#)+1
INTO a_num
FROM APPLICANT;
INSERT INTO APPLICANT VALUES (a_num,a_fname,a_lname,a_address,a_city,a_state,a_phone,a_fax,a_email,a_acomment);
COMMIT;
DBMS_OUTPUT.PUT_LINE('APPLICANT HAS SUCCESSFULLY ADDED');
EXCEPTION
WHEN Fail THEN
ROLLBACK;
WHEN OTHERS THEN
DBMS_OUTPUT.PUT_LINE(SQLERRM);
ROLLBACK;
END;
END;
END INSAPP;
/
But when i trying to execute it with this code,it give me an error message like this
Warning: Pcedure created with compilation errors.
Then i trying to show the erros:
- 49/1 PLS-00103: Encountered the symbol "END"
Did i make any mistake on the pl/sql code? Please correct me as i'm still new to pl/sql. Thanks and very appreciate that. :)

if you execute it from sqlplus, please try
EXEC INSAPP ( 000001, 'PETER', 'JONES', '7 STATION ST.', 'PERTH', 'WA', 645278453, NULL, NULL, 'Job expectations ? Money, money, money, ...' );
or wrap it inside begin .. end block
begin
INSAPP ( 000001, 'PETER', 'JONES', '7 STATION ST.', 'PERTH', 'WA', 645278453, NULL, NULL, 'Job expectations ? Money, money, money, ...' );
end;
/
UPD.
I think that you procedure is not compiled.
You cannot change value of input parameter a_num (by the way, it is not best to get new id for table, use sequences)
SELECT MAX(a#)+1
INTO a_num
FROM APPLICANT;
You have unnecessary END; after rollback statement in when section
Due to fact that compare null values always return false it is not good to search record by this condition
WHERE fname = a_fname AND
lname = a_lname AND
address = a_address AND
city = a_city AND
state = a_state AND
phone# = a_phone AND
fax# = a_fax AND
email = a_email AND
acomment = a_acomment;

Related

Insert Data Into Table with Stored Procedure in Oracle SQL

I am working through a homework assignment and am stuck on a problem with stored procedures.
I have the following tables:
create table Restaurant(rID int, name varchar2(100), address varchar2(100), cuisine varchar2(100));
create table Reviewer(vID int, name varchar2(100));
create table Rating(rID int, vID int, stars int, ratingDate date);
For my stored procedure I need to create, I get an input of a restaurant name (unique), reviewer name(unique), star rating, and review date. I need to update the Rating table with the proper information, and add a new reviewer to the Review table if they have not previously existed in the table.
In order to start my stored procedure, I wanted to start with just creating a new table called newReview to get the inputs stored in a new table, before re-writting to update the existing tables.
Here is the newReview Table
CREATE TABLE newReview(
RestaurantName VARCHAR(100),
UserName VARCHAR(100),
Stars Int,
RatingDate Date
)
This is my AddNewReview procedure, which compiles with success:
CREATE OR REPLACE PROCEDURE AddNewReview(
RESTAURANTNAME IN VARCHAR2 (100)
, USERNAME IN VARCHAR2 (100)
, Stars IN NUMBER
, RATINGDATE IN DATE
) AS
BEGIN
INSERT INTO newReview VALUES (RestaurantName, UserName, Stars, RatingDate);
END AddNewReview;
;
However, when I run the stored procedure with inputs as such,
BEGIN
AddNewReview ('Rangoli', 'Sarah M.', 4, '2020-11-21');
END;
I get the following error:
Error starting at line : 20 in command -
BEGIN
AddNewReview ('Rangoli', 'Sarah M.', 4, '2020-11-21');
END;
Error report -
ORA-06550: line 2, column 5:
PLS-00905: object TOCONN22.ADDNEWREVIEW is invalid
ORA-06550: line 2, column 5:
PL/SQL: Statement ignored
06550. 00000 - "line %s, column %s:\n%s"
*Cause: Usually a PL/SQL compilation error.
*Action:
I have tried defining the date input as DATE '2020-11-21' and also switching the single quote to double. Where am I going wrong, as this is the first stored procedure I am writing.
Try to change Stars data type from NUMBER to Int
AS:
CREATE OR REPLACE PROCEDURE AddNewReview(
RESTAURANTNAME IN VARCHAR2 (100)
, USERNAME IN VARCHAR2 (100)
, Stars IN NUMBER
, RATINGDATE IN DATE
) AS
BEGIN
INSERT INTO newReview VALUES (RestaurantName, UserName, Stars, RatingDate);
END AddNewReview;
;
to
CREATE OR REPLACE PROCEDURE AddNewReview(
RESTAURANTNAME IN VARCHAR2 (100)
, USERNAME IN VARCHAR2 (100)
, Stars IN Int
, RATINGDATE IN DATE
) AS
BEGIN
INSERT INTO newReview VALUES (RestaurantName, UserName, Stars, RatingDate);
END AddNewReview;
;
You need to look up the ids for the insertion:
CREATE OR REPLACE PROCEDURE AddNewReview (
in_RESTAURANTNAME IN VARCHAR2(100),
in_USERNAME IN VARCHAR2(100),
in_Stars IN NUMBER,
in_RATINGDATE IN DATE
) AS
BEGIN
INSERT INTO newReview (rid, vid, stars, RatingDate)
SELECT r.id, rr.id, in_stars, in_RatingDate
FROM restaurant r JOIN
reviewer rr
ON r.name = in_RestaurantName AND
rr.name = in_UserName
END AddNewReview;
This joins to the reference tables to get the ids you need. It will not insert the review if either name does not match. Your question doesn't specify what to do in that case, so that seems like reasonable behavior.
Note that the parameters are named so they don't conflict with column names. And this has listed all columns for the insert -- both are best practices.
Parameters are defined only by name and data type, they do not contain size specification. So your procedure needs:
create or replace procedure addnewreview(
restaurantname in varchar2
, username in varchar2
, stars in int
, ratingdate in date
...
You need to use To_Date function while calling the stored procedure, like below
BEGIN
AddNewReview ('Rangoli', 'Sarah M.', 4, TO_DATE('2020-11-21','YYYY-MM-DD'));
END;

Oracle sql - Errors creating a procedure

I've created this procedure
create or replace procedure enrollstudent(
rno in STUDENTS.ROLL_NUMBER%type,
sname in STUDENTS.STUDENT_NAME%type,
cid in STUDENTS.COURSEID%type,
cfees in STUDENTS.FEES%type,
spercent in students.percentage%type
)as
discount number;
begin
discount := spercent*5;
cfees := cfees-discount;
insert into STUDENTS values(rno, sname, cid, cfees, spercent);
commit;
end;
that works with this table
CREATE TABLE STUDENTS(
ROLL_NUMBER NUMBER(20) NOT NULL,
STUDENT_NAME VARCHAR2(25) NOT NULL,
COURSEID NUMBER(20) NOT NULL,
FEES NUMBER(20) ,
PERCENTAGE NUMBER(20)
);
When I run the procedure creation I have a Procedure ENROLLSTUDENT compiled and it gets created but i have the following errors in the compiler log
Error(8,1): PL/SQL: Statement ignored
Error(8,1): PLS-00363: expression 'CFEES' cannot be used as an assignment target
If I try to run the procedure with some data I simple have PLS-00905: object [schema].ENROLLSTUDENT is invalid
CFEES is an IN parameter. You can't change it. Create a local variable, and
use that, example:
cfees2 NUMBER := cfees;
cfees2 := cfees2 - discount;
insert into STUDENTS values(rno, sname, cid, cfees2, spercent);
You don't need to define and calculate any local variables; you can do the computation of cfees in place (right in the INSERT statement):
create or replace procedure enrollstudent(
rno in STUDENTS.ROLL_NUMBER%type,
sname in STUDENTS.STUDENT_NAME%type,
cid in STUDENTS.COURSEID%type,
cfees in STUDENTS.FEES%type,
spercent in students.percentage%type
)as
begin
insert into STUDENTS values(rno, sname, cid, cfees-spercent*5, spercent);
commit;
end;
/

Select Command in a procedure in SQL (ORACLE)

I have this piece of code:
CREATE OR REPLACE PROCEDURE MOSTRA_LOG (P_CODIGO_CLIENTE CLIENTE.CODIGO_CLIENTE%TYPE,N_LOG OUT, CODIGO_CLIENTE OUT, EMAIL OUT,TELEFONE OUT, NOME OUT, TIPO OUT) IS
BEGIN
SELECT (N_LOG, CODIGO_CLIENTE, EMAIL ,TELEFONE, NOME, TIPO) FROM LOG WHERE
(CODIGO_CLIENTE=P_CODIGO_CLIENTE);
END;
I know a procedure isn't the optimal thing to do but it is required in my case. It complains about an into clause that needs to be added, however I have nothing to "select into".
All I want basically is to show on the screen everything from the table LOG with the CODIGO_CLIENTE sent as a parameter.
EDIT:
After a suggestion I changed it to this:
CREATE OR REPLACE PROCEDURE MOSTRA_LOG (P_CODIGO_CLIENTE CLIENTE.CODIGO_CLIENTE%TYPE, N_LOGO OUT INTEGER, CODIGO_CLIENTEO OUT INTEGER, EMAILO OUT VARCHAR(30), TELEFONEO OUT NUMERIC(9,0), NOMEO OUT VARCHAR(50), TIPOO OUT VARCHAR(20)) IS
BEGIN
SELECT (N_LOG into N_LOGO, CODIGO_CLIENTE into CODIGO_CLIENTEO, EMAIL into EMAILO, TELEFONE into TELEFONEO, NOME into NOMEO, TIPO into TIPOO) FROM LOG WHERE (CODIGO_CLIENTE=P_CODIGO_CLIENTE);
END;
It's still going wrong saying it expects a symbol when it encountered "(".
Try this way using collections:
First you must create the collection where you will store your LOG query results:
CREATE TYPE LOG_OBJECT AS OBJECT
(CODIGO_CLIENTEO INTEGER,
EMAILO VARCHAR (30),
TELEFONEO NUMERIC (9, 0),
NOMEO VARCHAR (50),
TIPOO VARCHAR (20));
CREATE TYPE LOG_TABLE AS TABLE OF LOG_OBJECT;
Later you create your procedure like this:
CREATE OR REPLACE PROCEDURE MOSTRA_LOG (P_CODIGO_CLIENTE CLIENTE.CODIGO_CLIENTE%TYPE, LOG_T OUT LOG_TABLE) IS
BEGIN
SELECT LOG_OBJECT(N_LOG, CODIGO_CLIENTE, EMAIL ,TELEFONE, NOME, TIPO) BULK COLLECT INTO LOG_T FROM LOG WHERE
(CODIGO_CLIENTE=P_CODIGO_CLIENTE);
END;
When procedure is created you can use the collection like it was a table. For example below anonymus block prints total of rows of your query on LOG table:
DECLARE
LOG_T LOG_TABLE;
total NUMBER;
BEGIN
mostra_log (LOG_T); --invoke the procedure and fill the collection
SELECT COUNT (*) INTO total FROM TABLE (LOG_T); -- get count of collection returned
DBMS_OUTPUT.put_line (total);
END;

Oracle procedure call results in "PLS-00306: wrong number or types of arguments in call"

I'm trying to create a procedure in SQL. It compiles correctly with no errors, but when I try to run it I keep getting the same syntax error.
Here is the error:
exec reset_password(2002)
Error report -
ORA-06550: line 1, column 7:
PLS-00306: wrong number or types of arguments in call to 'RESET_PASSWORD'
ORA-06550: line 1, column 7:
PL/SQL: Statement ignored
06550. 00000 - "line %s, column %s:\n%s"
*Cause: Usually a PL/SQL compilation error.
*Action:
My query:
CREATE OR REPLACE PROCEDURE reset_password
(
p_customer_id NUMBER,
p_ret_code OUT NUMBER,
p_ret_message OUT VARCHAR2
)
AS
old_password VARCHAR2(10);
new_password VARCHAR2(10);
vnumb NUMBER;
ret_code NUMBER;
ret_message VARCHAR2(50);
Begin
Select count(*)
into vnumb
from customer
where customer_id = p_customer_id;
If vnumb = 0 then
ret_code:= 11;
ret_message:= 'help';
Else
ret_code:= 69;
ret_message:= 'train';
return;
end if;
p_ret_code:= ret_code;
p_ret_message:= ret_message;
end reset_password;
CREATE TABLE customer
( CUSTOMER_ID NUMBER PRIMARY KEY,
PASSWORD VARCHAR2(20) NOT NULL,
NAME VARCHAR2(20) NOT NULL,
EMAIL_ADDRESS VARCHAR2(50) NOT NULL,
PHONE_NUMBER VARCHAR2(15) NOT NULL,
REGISTRATION_DATE DATE NOT NULL,
EXPIRATION_DATE DATE NOT NULL,
LAST_UPDATE_DATE DATE NOT NULL);
INSERT INTO customer
VALUES(2001, 'CpsBTKpN','SMITH','smith#yahoo.com', '3123622345',
'02-FEB-2010', '01-FEB-2015', '02-FEB-2010');
INSERT INTO customer
VALUES(2002, 'ZWNWnQJT9', 'JONES', 'jones#hotmail.com', '6302077890',
'03-MAR-2010', '02-MAR-2015', '31-DEC-2010');
INSERT INTO customer
VALUES(2003, 'gc88Wmvpx', 'MILLER', 'miller#abc.com', '6303551234',
'09-APR-2010', '08-APR-2015', '09-APR-2010');
INSERT INTO customer
VALUES(2004, 'KcxweSYg555', 'JOHNSON', 'jo12#gmail.com', '7732015678',
'22-APR-2010', '21-APR-2015', '22-APR-2010');
INSERT INTO customer
VALUES(2005, 'CDYe44BBXd', 'CLARK', 'clark12#dpu.edu', '8476391001',
'18-MAY-2010', '17-MAY-2015', '18-MAY-2010');
INSERT INTO customer
VALUES(2006, 'xGqmkw345zr', 'LEWIS', 'lewis#ual.com', '2246166666',
'20-MAY-2010', '19-MAY-2015', '20-MAY-2010');
INSERT INTO customer
VALUES(2007, 'Y79zAHQwcB', 'KING', 'king#yahoo.com', '3018551234',
'30-JUN-2010', '29-JUN-2015', '30-JUN-2010');
INSERT INTO customer
VALUES(2008, 'vhSDHMDg66', 'SCOTT', 'scott#hotmail.com', '7701239876',
'30-AUG-2010', '30-DEC-2011', '30-DEC-2011');
COMMIT;
To run your procedure, one can create an anonymous plsql block with a declaration associated with the out parameters:
p_ret_code OUT NUMBER,
p_ret_message OUT VARCHAR2
Apparently, you are not passing three parameters (two being out) with your procedural invocation. This is why you are receiving the error:
PLS-00306: wrong number or types of arguments in call to 'RESET_PASSWORD'
I use l_ret_code and l_ret_message with matching data types.
DECLARE
l_ret_code NUMBER;
l_ret_message VARCHAR(50);
BEGIN
reset_password ( 2002, l_ret_code, l_ret_message);
END;
If one would like to use the execute command to run the procedure with the out parameters, using bind variables will work:
var l_ret_code NUMBER;
var l_ret_message VARCHAR2(50);
EXECUTE reset_password ( 2002, :l_ret_code, :l_ret_message);

check age trigger from two separate tables in oracle sql

I need to create a trigger that checks that the age (in years) of the participant is higher than the minimum age of the race he/ she participates in. To do this I need to get information from the participants table and the race table. I need to add this trigger to the results table
here are my tables:
CREATE TABLE race
(
RaceID int,
Location varchar2 (60),
StartDate Date,
RaceTime Date,
MinAge int,
);
CREATE TABLE participant
(
ParticipantID int,
"Name" varchar2 (60),
DateOfBirth date,
Sex varchar2 (1),
Age int
);
CREATE TABLE results
(
RaceID int not null unique,
ParticipantID int not null unique,
position number (2)
);
here is what I have created so far:
create or replace TRIGGER dob_trg
BEFORE INSERT OR UPDATE ON RESULTS
FOR EACH ROW
DECLARE
RACE_MINAGE NUMBER;
PARTICIPANT_AGE NUMBER;
BEGIN
SELECT RACE.MINAGE, PARTICIPANT.AGE
INTO RACE_MINAGE, PARTICIPANT_AGE
FROM RACE PARTICIPANT
WHERE RACE.RACEID = :NEW.RACEID;
IF : NEW.AGE < : NEW.MINAGE THEN
RAISE_APPLICATION_ERROR(-20000, 'Participant too young!');
END IF;
enddob_trg;
However I'm getting the following error
Error(9,6): PLS-00103: Encountered the symbol ":"
Any help greatly appreciated!
Erros :
Table race - there is an extra comma at the end of you MinAge col
CREATE TABLE race
(
RaceID int,
Location varchar2 (60),
StartDate Date,
RaceTime Date,
MinAge int,
);
Inside trigger errors:
IF : NEW.AGE < : NEW.MINAGE THEN should be
IF :NEW.AGE < :NEW.MINAGE THEN
Your create trigger is on table RESULTS but the action is made on a column called AGE that belongs to the participant table .
Fix this logic before going forward.
One more error inside your trigger :
FROM RACE PARTICIPANT
add a comma between tables
Fixed trigger
-here i what i think your trigger should look like !
Compile it and give it a try
See my logic :
This query will store the values of minage using the predicate "NEW.ParticipantID"
SELECT RACE.MINAGE, PARTICIPANT.AGE
INTO RACE_MINAGE, PARTICIPANT_AGE
FROM RACE, PARTICIPANT
WHERE RACE.RACEID = :NEW.ParticipantID;
This part :- if the RACE_MINAGE is bigger or equal then
IF :NEW.AGE <= RACE_MINAGE THEN
RAISE_APPLICATION_ERROR(-20000, 'Participant too young!');
END IF;
Complete trigger
CREATE OR REPLACE TRIGGER dob_trg
BEFORE INSERT OR UPDATE ON participant
FOR EACH ROW
DECLARE
RACE_MINAGE NUMBER;
PARTICIPANT_AGE NUMBER;
BEGIN
SELECT RACE.MINAGE, PARTICIPANT.AGE
INTO RACE_MINAGE, PARTICIPANT_AGE
FROM RACE, PARTICIPANT
WHERE RACE.RACEID = :NEW.ParticipantID;
exception
when NO_DATA_FOUND then
NULL; -- or do something else you choose
IF :NEW.AGE <= RACE_MINAGE THEN
RAISE_APPLICATION_ERROR(-20000, 'Participant too young!');
END IF;
end;
IF : NEW.AGE < : NEW.MINAGE THEN
You should remove the whitespace after the : symbol.
IF :NEW.AGE < :NEW.MINAGE THEN
Also, it looks like you're missing a comma in your FROM clause:
FROM RACE PARTICIPANT
But that wouldn't make your code work yet, because you're testing the wrong fields in your IF statement. Also, you're not filtering the participantId.