Integrity constraint violated - parent key not found when calling stored procedure - oracle

I'm trying to perform the stored package procedure call in Oracle 11g XE, but for some reason I get the error below:
Error report - ORA-02291: integrity constraint (ROOT.SYS_C007057)
violated - parent key not found ORA-06512: at "ROOT.BOOKS_STORE", line
69 ORA-06512: at line 2
02291. 00000 - "integrity constraint (%s.%s) violated - parent key not found"
*Cause: A foreign key value has no matching primary key value.
*Action: Delete the foreign key or add a matching primary key.
when calling the following procedure:
begin
books_store.add_books_to_store(
'To Kill a Mockingbird', 21,
'test description', 5,
'https://test_img.jpg',
10, 6.99
);
end;
What the procedure does is insert the data into the books table. Below is the procedure text (which is inside the books_store package) and the description of the books table.
procedure add_books_to_store(
book_name books.name%type, book_author_id books.author_id%type,
book_description books.description%type default null,
book_publisher_id books.publisher_id%type, book_cover_img books.cover_img%type,
books_count books.available_count%type, book_price books.price%type)
is
existing_books_count integer;
add_negative_or_zero_books exception;
begin
if books_count <= 0 then
raise add_negative_or_zero_books;
end if;
select count(*) into existing_books_count from books
where
name = book_name and author_id = book_author_id and
description = book_description and publisher_id = book_publisher_id and
price = book_price;
if existing_books_count = 0 then
insert into books values (books_seq.nextval, book_name, book_description,
book_cover_img, books_count, book_author_id, book_publisher_id, book_price);
else
update books set available_count = available_count + books_count
where
name = book_name and author_id = book_author_id and
description = book_description and publisher_id = book_publisher_id and
price = book_price;
end if;
exception
when add_negative_or_zero_books then
raise_application_error(-10003, 'You cannot add 0 or less books');
end add_books_to_store;
books description:
DESC books;
Name Null? Type
------------------------------------------------------------
ID NOT NULL NUMBER(5)
NAME NOT NULL VARCHAR2(200)
DESCRIPTION VARCHAR2(2000)
COVER_IMG VARCHAR2(300)
AVAILABLE_COUNT NOT NULL NUMBER(4)
PRICE NUMBER(10,2)
AUTHOR_ID NUMBER(5)
PUBLISHER_ID NUMBER(5)
So, the error says that there's something wrong with my primary or foreign keys. Though, I cannot understand what exactly is wrong.
I thought that the problem was that I passed wrong author_id and publisher_id as arguments to the procedure, but they're correct. Here's the select * calls for authors and publishers tables:
select * from authors;
ID FIRST_NAME LAST_NAME BIRTHDAY
--------------------------------------------------
21 Harper Lee 28-APR-26
select * from publishers;
ID NAME
---------------------------
5 Penguin Fiction
Could you help me to find out what's wrong with my code and how to make it work?
PS: Here's my ER-diagram:

I think, problem could be here:
insert into books values (books_seq.nextval, book_name, book_description,
book_cover_img, books_count, book_author_id, book_publisher_id, book_price);
Because in table description columns have another order:
PRICE NUMBER(10,2)
AUTHOR_ID NUMBER(5)
PUBLISHER_ID NUMBER(5)
Try to specify column names explicitly:
insert into books (ID, NAME, DESCRIPTION, COVER_IMG, AVAILABLE_COUNT, PRICE, AUTHOR_ID, PUBLISHER_ID)
values (books_seq.nextval, book_name, book_description,
book_cover_img, books_count, book_price, book_author_id, book_publisher_id);
Now it looks like you are inserting AUTHOR_ID value into PRICE column, PUBLISHER_ID into AUTHOR_ID and PRICE into PUBLISHER_ID.

Related

Trigger error: ORA-01403 no data found on insert

My database is that of a hotel reservation system. My trigger will change the availability status of a room before any new reservations are made based on whether the current date falls between the check_in and check_out values of a room.
I getting the error no data found when attempting to fire the trigger with an insert statement. I would appreciate any assistance with the problem.
Error:
SQL Error: ORA-01403: no data found
ORA-06512: at "USER.ROOM_STATUS", line 5
ORA-04088 error during execution of trigger 'USER.ROOM_STATUS' - no data found
*Cause: No data was found from the objects
Trigger:
create or replace trigger room_status
before insert on reservation
for each row
declare
status_in room.status%type;
error1 exception;
begin
select status into status_in
from room
where room.room_id = :old.room_id;
if sysdate between :old.check_in and :old.check_out then
update room
set status = 'F'
where room_id = :old.room_id;
else
update room
set status = 'T'
where room_id = :old.room_id;
end if;
exception
when error1 then
raise_application_error(-20100,'Insert Cancelled');
end;
Insert Statement:
insert into reservation
values(reservation_sequence.nextval,to_date('05-03-2017','mm/dd/yyyy'),
to_date('05-07-2017','mm/dd/yyyy'), 116, 170);
Tables:
create table roomType
(room_type varchar2(20) constraint roomType_pk primary key,
room_rate number(4));
create table room
(room_id number(3) constraint room_pk primary key,
room_type varchar2(15) constraint room_fk references roomType,
status char(1));
create table guest
(guest_id varchar2(5) constraint guest_pk primary key,
first_name varchar2(20),
last_name varchar2(20),
email varchar2(30),
phone varchar2(10));
create table reservation
(reservation_id number(6) constraint reservation_pk primary key,
check_in date,
check_out date,
room_id number(3),
guest_id varchar2(5),
foreign key (room_id) references room(room_id),
foreign key (guest_id) references guest(guest_id));
Oracle throws the NO_DATA_FOUND error when a SELECT statement finds no data. So, looking at your trigger, the obvious explanation might be there is no data in your ROOM table.
However, there is a subtle bug in your trigger code:
select status into status_in
from room
where room.room_id = :old.room_id;
The :old namespace references the value of the column before the DML is applied. But your DML statement is an insert so the values of :old.room_id is null because there is no prior record. Anything = null is always false so the select fails to find anything.
What you need to do is reference the :new value.
select status into status_in
from room
where room.room_id = :new.room_id;
:new applies to INSERT and UPDATE statements, :old applies to UPDATE and DELETE statements.
Incidentally you have defined an exception error1 but you don't raise it anywhere so that exception handler will never execute.

Oracle fetch returns more than requested

So I've got another simple procedure with an error. This time, the fetch is returning more records than requested. I initially checked my query and found an error. My query returns the right results, but the fetch still won't work.
PROCEDURE:
--View Customer Service History
create or replace procedure SERVICEHISTORY(name in customer.name%type) is
carModel char(11);
serviceCharge decimal(7,2);
serviceName char(20);
serviceDate date;
cusName char(15);
cusID number;
--Query tested, it works
cursor nextService is
select name, workOrder.serviceDate, workOrderServices.actualCharge
from workOrder join workOrderServices on workOrder.workOrderID=workOrderServices.workOrderID join services on workOrderServices.serviceID=services.serviceID
where workOrderServices.customerID=cusID;
begin
--Get customer ID from name, another janky work around
select customerID
into cusID
from customer
where customer.name=name;
--Gets the car model
select model
into carModel
from vehicle
where vehicle.customerID=cusID;
open nextService;
fetch nextService into serviceName, serviceDate, serviceCharge;
if nextService%notfound then
dbms_output.put_line('No service history found.');
else
dbms_output.put_line('Service-------Date-------Cost');
loop
dbms_output.put_line(serviceName||' '||serviceDate||' '||serviceCharge);
fetch nextService into serviceName, serviceDate, serviceCharge;
if nextService%notfound then
dbms_output.put_line('Report finished.');
end if;
exit when nextService%notfound;
end loop;
end if;
close nextService;
end serviceHistory;
/
But it throws this error:
ERROR:
ORA-01422: exact fetch returns more than requested number of rows
ORA-06512: at line 20
ORA-06512: at line 1
Here are the tables:
create table customer
(
customerID number(8) not null primary key constraint lengthCHK13 check(LENGTH(customerID)=8),
name varchar2(20) not null,
address varchar2(20) not null,
insurance varchar2(20) not null,
contactInfo number(10) not null,
customerType varchar2(15) not null,
licenseNumber varchar2(13) not null,
amountOwed decimal(7,2) not null constraint notNeg6 check(amountOwed >=0)
);
create table vehicle
(
--some error about no matching unique or primary key for this column on cusomterID
VIN varchar2(17) not null primary key constraint lengthCHK113 check(length(VIN)=17),
customerID number(8) not null references customer(customerID) constraint lengthCHK12 check(length(customerID)=8),
make varchar2(10) not null,
model varchar2(10) not null,
carYear number(4) not null,
color varchar2(10) not null,
notes varchar2(20),
currentMileage number(6) not null,
engineType varchar2(10) not null,
licenseNumber varchar(12) not null,
amountOwed decimal(7,2) constraint notNeg7 check(amountOwed >=0)
--primary key(VIN, customerID) DOESNT WORK BUT NEEDS TO
);
create table workOrder
(
workOrderID number(8) not null constraint lengthCHK10 check(length(workOrderID)=8),
VIN varchar2(17) not null references vehicle(VIN) constraint lengthCHK14 check(length(VIN)=17),
serviceDate date not null,
--Removing b/c it's a pain serviceTime TIME not null,
serviceBay number(2),
description varchar2(20) not null,
results varchar2(20) not null,
primary key(workOrderID)
);
create table services
(
serviceID number(8) not null primary key constraint lengthCHK17 check(length(serviceID)=8),
name varchar2(20) not null,
price decimal(7,2) not null constraint notNeg8 check(price >=0),
estimatedHours number(2) not null
);
create table workOrderServices
(
serviceID number(8) not null references services(serviceID) constraint lengthCHK20 check(length(serviceID)=8),
workOrderID number(8) not null references workOrder(workOrderID) constraint lengthCHK22 check(length(workOrderID)=8),
customerID number(8) not null references customer(customerID) constraint lengthCHK87 check(length(customerID)=8),
actualHours number(2) not null constraint notNeg11 check(actualHours >=0),
actualCharge decimal(7,2) not null constraint notNeg10 check(actualCharge >=0),
primary key(serviceID, workOrderID)
);
Test data:
INSERT INTO services(serviceID, name, price, estimatedHours)
VALUES(48937322, 'Tire Rotate', 19.99, 1);
INSERT INTO services(serviceID, name, price, estimatedHours)
VALUES(47873231, 'Xmission Flush', 63.99, 1);
INSERT INTO customer (customerID, name, address, insurance, contactInfo, customerType, licenseNumber, amountOwed)
VALUES (45124512, 'Bob Jones', '232 Sycamore Ln.', 'Pekin', 3095555145, 'New', 'SSSSFFFYYDDD', 220.00);
INSERT INTO customer (customerID, name, address, insurance, contactinfo, customertype, licensenumber, amountOwed)
VALUES (12892222, 'Mike Tyson','100 Haters Rd.', 'Progressive', 2175555555, 'Regular', 'FGHJHHHHTYYY', 42.00);
INSERT INTO vehicle(VIN, customerID, make, model, carYear, color, notes, currentMileage, engineType, licenseNumber, amountOwed)
VALUES('KNDKG3A31A7568300', 45124512, 'Ford', 'Focus', 2009, 'Red', 'side door damage', 10346, 'V4', 'h5303h87dk23', 0);
INSERT INTO vehicle(VIN, customerID, make, model, carYear, color, notes, currentMileage, engineType, licenseNumber, amountOwed)
VALUES('SALTW16413A376838', 12892222, 'Chrysler', 'Sebring', 2004, 'Green', 'Basically a Go-Kart', 105098, 'V4', 'r2345h23tx31', 0);
INSERT INTO workOrder( workOrderID, VIN, serviceDate, serviceBay, description, results)
VALUES(12312312, 'KNDKG3A31A7568300', '07-FEB-12', 2, 'Oil Change', 'Changed oil');
INSERT INTO workOrder( workOrderID, VIN, serviceDate, serviceBay, description, results)
VALUES(32132132, 'SALTW16413A376838', '07-FEB-12', 3,'Tire Rotation', 'Rotated the tires');
INSERT INTO workOrderServices(serviceID, workOrderID, customerID, actualHours, actualCharge)
VALUES(17278722, 12312312, 45124512, 5, 45.00);
INSERT INTO workOrderServices(serviceID, workOrderID, customerID,actualHours, actualCharge)
VALUES(48937322, 32132132, 12892222,10, 90.00);
If you had put some extra messaging into your code, as I did, you would have quickly discovered the source of the error.
create or replace procedure SERVICEHISTORY(name in customer.name%type) is
carModel char(11);
serviceCharge decimal(7,2);
serviceName char(20);
serviceDate date;
cusName char(15);
cusID number;
--Query tested, it works
cursor nextService is
select name, workOrder.serviceDate, workOrderServices.actualCharge
from workOrder
join workOrderServices
on workOrder.workOrderID=workOrderServices.workOrderID
join services on workOrderServices.serviceID=services.serviceID
where workOrderServices.customerID=cusID;
begin
dbms_output.put_line('Get customer ID from name, another janky work around');
select customerID
into cusID
from customer
where customer.name=name;
dbms_output.put_line('cusID='||cusID);
--Gets the car model
select model
into carModel
from vehicle
where vehicle.customerID=cusID;
dbms_output.put_line('carModel='||carModel);
open nextService;
fetch nextService into serviceName, serviceDate, serviceCharge;
if nextService%notfound then
dbms_output.put_line('No service history found.');
else
dbms_output.put_line('Service-------Date-------Cost');
loop
dbms_output.put_line(serviceName||' '||serviceDate||' '||serviceCharge);
fetch nextService into serviceName, serviceDate, serviceCharge;
if nextService%notfound then
dbms_output.put_line('Report finished.');
end if;
exit when nextService%notfound;
end loop;
end if;
close nextService;
end serviceHistory;
/
Here's my output:
SQL> exec SERVICEHISTORY(name=>'Bob Jones')
Get customer ID from name, another janky work around
BEGIN SERVICEHISTORY(name=>'Bob Jones'); END;
*
ERROR at line 1:
ORA-01422: exact fetch returns more than requested number of rows
ORA-06512: at "APC.SERVICEHISTORY", line 23
ORA-06512: at line 1
It's the very first query which hurls. Why does it do that? Because you've given the parameter the same name as the column. In PL/SQL variable naming has scope, with the nearest declaration trumping further ones.
So in your query ...
select customerID
into cusID
from customer
where customer.name=name;
... Oracle interprets name on the right-hand side as being the column of the table, because that's the narrowest scope. Effectively your filter is where 1=1, which is no filter at all.
All you need to do to fix this is change the parameter to something like p_name and use that in your query instead...
SQL> exec SERVICEHISTORY(p_name=>'Mike Tyson')
Get customer ID from name, another janky work around
cusID=12892222
carModel=Sebring
Service-------Date-------Cost
Tire Rotate 07-FEB-12 90
Report finished.
PL/SQL procedure successfully completed.
SQL>
Of course, you will get the same error from the query on VEHICLE should you customer have more than one car, which the data model supports.
At the moment you don't use the result from that query, so the easiest fix would be to remove it. But probably you want to include it in the output, so the best solution might be to include VEHICLE in the main query.

Triggers in oracle PL/SQL

I am trying to do a trigger that updates a sum of all credits on update of the grade or a insert of a new one. That's my tables
create table Department (
Department_ID varchar(4) not null,
Name varchar(25) unique,
Department_Head_ID varchar(9),
College_ID varchar(4),
Credits_To_Degree NUMBER(3),
constraint pkDepartment primary key (Department_ID));
create table Enrollment (
Student_ID varchar(9) not null,
Course_ID varchar(5) not null,
Registered_Date date,Grade NUMBER,
Status varchar(4),constraint pkEnrollment primary key
(Student_ID, Course_ID));
create table Student (
Student_ID varchar(9) not null,
First_Name varchar(25),
Last_Name varchar(25),
Phone char(11),
Birth_Date date,
Street varchar(100),
Zip_Code char(5),
Department varchar(4),
Credits integer,
Eligible char(4), constraint pkStudent primary key
(Student_ID),constraint fkDeptId foreign key (Department)
references Department(Department_ID));
ALTER TABLE Department ADD FOREIGN KEY (Department_Head_ID)
REFERENCES Faculty(Faculty_Id) INITIALLY DEFERRED;
ALTER TABLE Department ADD FOREIGN KEY(College_ID) REFERENCES
College(College_ID) INITIALLY DEFERRED;
the trigger:
create or replace TRIGGER Credits
after INSERT OR UPDATE
ON enrollment
REFERENCING NEW AS New OLD AS Old
FOR EACH ROW
BEGIN
UPDATE STUDENT
SET CREDITS=(SELECT SUM(c.CREDITS) FROM COURSE c,ENROLLMENT e
WHERE c.COURSE_ID = e.COURSE_ID
and e.STUDENT_ID = :new.student_id
and e.GRADE>= 60 )
WHERE STUDENT.STUDENT_ID=:new.student_id;
END;
The trigger compiles but when i change value of the grade a get this error
UPDATE "FELIX"."ENROLLMENT" SET GRADE = '60' WHERE ROWID = 'AAAGUSAABAAALKJAAF' AND ORA_ROWSCN = '3540016'
ORA-20003: An error has occurred while performing credits trigger
ORA-06512: at "FELIX.CREDITS", line 5
ORA-04088: error during execution of trigger 'FELIX.CREDITS'
One error saving changes to table "FELIX"."ENROLLMENT":
Row 6: ORA-20003: An error has occurred while performing credits trigger
ORA-06512: at "FELIX.CREDITS", line 5
ORA-04088: error during execution of trigger 'FELIX.CREDITS'
line 5 is a FOR EACH ROW command
I figure out that the problem is in the :new.student_id. But how could i get the id of the row that the triggers fires upon.
Thanks in advance for the help.

Why it tell "invalid identifier (ORA-00904)"? when I call function in CONSTRAINT CHECK

This is some kind of study database in sql file. I use oracle 11g and process it in sqlplus.
I wrote two function for check the course number and the department number, so its depend on the major and the minor department of each student.
For example, I am student of CS department (major) and BIO department (minor), so I can not enroll the course which is about math department.
When I call it in CHECK but I don't know why it told that.
This is output when I create all table, (from sqlplus)
....
....
....
table created.
ALTER TABLE sections ADD CONSTRAINT CK_course_depart CHECK (FindMYDeparture(stuid,find_dno_from_cno(cno)) = 'true');
ERROR at line 1:
ORA-0094: "FIND_DNO_FROM_CNO":invalid identifier
This is in .sql file
DROP TABLE department CASCADE CONSTRAINTS;
CREATE TABLE department (
dnumber number(4) not null,
dname varchar(25) not null,
primary key (dnumber)
);
DROP TABLE courses CASCADE CONSTRAINTS;
CREATE TABLE courses (
cno number(4) not null,
cname varchar(15) not null,
credit number(1) not null,
dnumber number(4) not null,
primary key (cno),
foreign key (dnumber) references department(dnumber),
CONSTRAINT credits CHECK (credit > 0 AND credit <= 5)
);
DROP TABLE student CASCADE CONSTRAINTS;
CREATE TABLE student (
stuid char(9) not null,
fname varchar(15) not null,
lname varchar(15) not null,
dMjno number(4) not null,
dMnno number(4),
primary key (stuid),
CONSTRAINT depart_M_n CHECK (dMjno <> dMnno),
CONSTRAINT dMinor_check CHECK (dMnno = 1 OR dMnno = 2 OR dMnno = 3)
);
DROP TABLE sections CASCADE CONSTRAINTS;
CREATE TABLE sections (
sno number(4) not null,
cno number(4) not null,
stuid char(9) not null,
semester varchar(6) not null,
year varchar(4) not null,
instructor varchar(15) not null,
CONSTRAINT combine_pk primary key (sno,stuid),
foreign key (cno) references courses(cno),
foreign key (stuid) references student(stuid),
CONSTRAINT cant_enroll CHECK (semester <> 'Spring' AND year <> 2007)
);
DROP TABLE grading CASCADE CONSTRAINTS;
CREATE TABLE grading (
sno number(4) not null,
stuid char(9) not null,
grade numeric(1,2),
foreign key (sno,stuid) references sections(sno,stuid),
foreign key (stuid) references student(stuid),
CONSTRAINT grading_check CHECK (grade >= 0 AND grade <= 4)
);
DROP FUNCTION FindMYDeparture;
CREATE OR REPLACE FUNCTION FindMYDeparture(stuid_in IN char,depart_course IN NUMBER)
RETURN NUMBER AS
departMa_no NUMBER;
departMi_no NUMBER;
report varchar(10);
CURSOR cdno is
SELECT dMjno,dMnno FROM student WHERE stuid = stuid_in;
BEGIN
OPEN cdno;
LOOP
FETCH cdno INTO departMa_no,departMi_no;
IF (departMa_no = depart_course OR departMi_no = depart_course)
THEN
report := 'true';
EXIT;
ELSE
report := 'flase';
END IF;
EXIT WHEN cdno%NOTFOUND;
END LOOP;
CLOSE cdno;
RETURN report;
END;
/
DROP FUNCTION find_dno_from_cno;
CREATE OR REPLACE FUNCTION find_dno_from_cno(cno_in IN NUMBER)
RETURN NUMBER AS
depart_no NUMBER;
CURSOR cdno is
SELECT dnumber FROM courses WHERE cno = cno_in;
BEGIN
OPEN cdno;
FETCH cdno INTO depart_no;
CLOSE cdno;
RETURN depart_no;
END;
/
ALTER TABLE sections ADD CONSTRAINT CK_course_depart CHECK (FindMYDeparture(stuid,find_dno_from_cno(cno)) = 'true');
Not going to happen. You are not allowed to use your pl/sql functions in check constraint by design:
•Conditions of check constraints cannot contain the following
constructs:
•Subqueries and scalar subquery expressions
•Calls to the functions that are not deterministic (CURRENT_DATE,
CURRENT_TIMESTAMP, DBTIMEZONE, LOCALTIMESTAMP, SESSIONTIMEZONE,
SYSDATE, SYSTIMESTAMP, UID, USER, and USERENV)
•Calls to user-defined functions
•Dereferencing of REF columns (for example, using the DEREF function)
•Nested table columns or attributes
•The pseudocolumns CURRVAL, NEXTVAL, LEVEL, or ROWNUM
•Date constants that are not fully specified
http://docs.oracle.com/cd/B19306_01/server.102/b14200/clauses002.htm
Try running every statement in that function, This is the case of non existent column for a table or using a not existing row.

SQL invalid identifier

I checked some of the SQL invalid identifier solutions, but none of them helped me to fix my prob.
CREATE OR REPLACE PROCEDURE add_order(
p_cust_id cust_order.cust_id%TYPE,
p_order_id cust_order.order_id%TYPE,
p_order_date cust_order.order_date%TYPE,
p_sales_made_by cust_order.sales_made_by%TYPE,
p_qty cust_order.qty%TYPE,
p_product_id cust_order.product_id%TYPE,
p_cust_charged cust_order.cust_charged%TYPE,
p_company_price cust_order.company_price%TYPE,
p_shipper_id cust_order.shipper_id%TYPE)
IS
BEGIN
IF p_shipper_id = 'FEDEX' OR p_shipper_id = 'USPS' OR p_shipper_id = 'CUST' THEN
INSERT INTO productss (cust_id, order_id, order_date, sales_made_by, qty,
product_id, cust_charged, company_price, shipper_id)
VALUES (p_cust_id, p_order_id, p_order_date, p_sales_made_by, p_qty,
p_product_id, p_cust_charged, p_company_price, p_shipper_id);
ELSE
dbms_output.PUT_LINE('This shipper IS NOT allowed');
END IF;
END add_order;
/
The error is:
17/1 PL/SQL: SQL Statement ignored
17/116 PL/SQL: ORA-00904: "SHIPPER_ID": invalid identifier
This is the table:
CREATE TABLE CUST_ORDER
(
CUST_ID NUMBER(15),
ORDER_ID NUMBER(20),
ORDER_DATE DATE,
SALES_MADE_BY VARCHAR(40),
QTY NUMBER,
PRODUCT_ID NUMBER,
CUST_CHARGED NUMBER,
COMPANY_PRICE NUMBER,
SHIPPER_ID NUMBER,
PRIMARY KEY (ORDER_ID),
FOREIGN KEY (CUST_ID) REFERENCES CUST_INFO(CUST_ID),
FOREIGN KEY (PRODUCT_ID) REFERENCES PRODUCTS(PRODUCT_ID)
FOREIGN KEY (SHIPPER_ID) REFERENCES SHIPPING(SHIPPER_ID)
);
I guess that it is obvious mistake, but I was working too much.
You have an extra 'S' in the PRODUCTS table name:
INSERT INTO PRODUCTSS
^
And as #Alex Poole points out, you appear to be inserting into the wrong table anyway, given the naming of the proc.

Resources