#sql #database #oracle #triggers #sql-insert
#sql #База данных #Oracle #триггеры #sql-insert
Вопрос:
Мой код показан ниже. Все работает правильно, но когда мои операторы insert нарушают триггер, он выдает ошибки из-за моего raise_application_error.
--Drop tables in case they were created previously
DROP TABLE enrollment Purge;
DROP TABLE offering Purge;
DROP TABLE faculty Purge;
DROP TABLE course Purge;
DROP TABLE student Purge;
--Create student table
CREATE TABLE student(StdID number(3) constraint student_StdID_PK primary key,
StdFN varchar2(10),
StdLN varchar2(15),
StdCity varchar2(15),
StdState char(2),
StdZip number(5),
StdMajor varchar2(4),
StdClass char(2),
StdGPA number(2,1),
StdBalance NUMBER (12,2));
--create a table for courses and their descriptions
CREATE TABLE course(CourseNo varchar2(8) constraint course_courseNo_PK primary key,
CrsDesc varchar2(40),
CrsCredits number(1));
--create faculty table
CREATE TABLE Faculty(FacID number(4) constraint faculty_FacID_PK primary key,
FacFN varchar2(10),
FacLN varchar2(15),
FacDept varchar2(4),
FacRank varchar2(4),
FacHireDate date,
FacSalary number(6),
FacSupervisor number(4));
--create table for offered courses
CREATE TABLE Offering(OfferNo number(4) constraint offering_OfferNo_PK primary key,
CourseNo varchar(8)constraint offering_crs_no references course(courseno),
OffTerm varchar2(6),
OffYear number(4),
OffLoca varchar(6),
OffTime varchar(8),
OffDay varchar(5),
FacSSN number(4)constraint offering_fac_FK references faculty(facID));
--create table for student enrollment
CREATE TABLE enrollment(StdID number(3),
OfferNo number(4),
EnrGrade char(2),
constraint enrollment_PK primary key (StdID,OfferNo),
constraint enrollment_std_ID foreign key(StdID) references student(stdID),
constraint enrollment_class_ID foreign key(offerno) references offering(offerno));
CREATE OR REPLACE TRIGGER UNPAID_BALANCE
BEFORE INSERT ON STUDENT
FOR EACH ROW
DECLARE
BAL NUMBER;
BEGIN
BAL := :NEW.STDBALANCE;
IF BAL > 500
THEN
RAISE_APPLICATION_ERROR(-20001, 'Your balance is too high to register. Please pay to continue.');
END IF;
END;
/
CREATE OR REPLACE TRIGGER ENROLL_MAX
BEFORE INSERT ON ENROLLMENT
FOR EACH ROW
DECLARE
NOFSTUDENTS BINARY_INTEGER;
BEGIN
SELECT COUNT(*) INTO NOFSTUDENTS
FROM ENROLLMENT
WHERE OFFERNO = :NEW.OFFERNO AND ENRGRADE IS NULL;
DBMS_OUTPUT.PUT_LINE(NOFSTUDENTS);
IF (NOFSTUDENTS 1) > 2
THEN
RAISE_APPLICATION_ERROR(-20003, 'EXCEED MAX NO OF STUDENTS ALLOWED');
END IF;
END;
/
--populate student table
INSERT INTO student values(101,'Joe','Smith','Eau Clare','WI',18121,'IS','FR',3.8,225.25);
INSERT INTO student values(102, 'Rob','King', 'Melrose', 'MN', 56352, 'IS','JR',3.2,120.98);
INSERT INTO student values(103, 'Dan','Robinson', 'Sartell', 'MN', 98042, 'IS','JR',3.6, 36);
INSERT INTO student values(104,'Sue','Williams','St.Cloud','MN',56301,'ACCT','SR',3.2,2386.55);
INSERT INTO student values(105,'Don','Robinson','St.Paul','MN',55103,'MKTG','SR',3.4, 306);
--populate course table
INSERT INTO Course values('CSCI 200','Elements of Computing',3);
INSERT INTO Course values('IS 250','Application of Program Dev. I',3);
INSERT INTO Course values('IS 251','Application of Program Dev. II',3);
INSERT INTO Course values('IS 454', 'Data Mining for Decision Support',3);
INSERT INTO Course values('IS 356','Systems Analysis and Design I',3);
INSERT INTO Course values('IS 460', 'Project Management',3);
INSERT INTO Course Values('ACCT 291','Accounting Principles II',3);
INSERT INTO Course values('IS 443','Database Design',3);
--populate faculty table
INSERT INTO faculty values(9001,'Leonard','Vince','IS','ASST','12-Apr-1997',67000,9003);
INSERT INTO faculty values(9002,'Victor','Strong','CSCI','ASSO','8-Aug-1999',70000,9003);
INSERT INTO faculty values(9003,'Nicki','Colan','IS','PROF','20-Aug-1981',75000,9010);
INSERT INTO faculty values(9004,'Fred','Wells','ACCT','ASST','28-Aug-1996',60000,9010);
INSERT INTO faculty values(9010,'Chris','Macon','ACCT','ASST','4-Aug-1980',75000,Null);
--populate offering table
INSERT INTO offering values(2201,'CSCI 200','Spring',2017,'ECC135','10:30AM','MWF',9002);
INSERT INTO offering values(2202,'CSCI 200','Spring',2017,'ECC135','8:00AM','MWF',9002);
INSERT INTO offering values(1102,'ACCT 291','Spring',2017,'CH 14A','2:00AM','MWF',9004);
INSERT INTO offering values(2203,'IS 356','Fall',2017,'CH494','3:30AM','TTH',9001);
INSERT INTO offering values(2204,'IS 251','Fall',2017,'CH494','12:30AM','TTH',9003);
INSERT INTO offering values(1101,'ACCT 291','Fall',2017,'CH350','12:30AM','TTH',9010);
INSERT INTO offering values(2205,'IS 443','Fall',2017,'CH494','9:30AM','MWF',9003);
--populate enrollment table
INSERT INTO enrollment values(101,2201,'A');
INSERT INTO enrollment values(102,2202,'B');
INSERT INTO enrollment values(102,2203,null);
INSERT INTO enrollment values(103,2203,null);
INSERT INTO enrollment values(103,2201,'C');
INSERT INTO enrollment values(103,1101,null);
INSERT INTO enrollment values(104,2202,'A');
INSERT INTO enrollment values(101,2203,null);
INSERT INTO enrollment values(101,1101,null);
INSERT INTO enrollment values(101,2205,null);
INSERT INTO enrollment values(102,2205,null);
INSERT INTO enrollment values(104,2205,null);
Есть ли способ, которым я могу сделать это более чистым / лучшим в разделе вывода скрипта, потому что одним из конкретных случаев является это сообщение об ошибке, которое появляется из-за ошибки приложения raise.
Ошибка, начинающаяся со строки: 129 в command —
ВСТАВИТЬ В значения регистрации (104 2202,’A’)
Отчет об ошибке —
ORA-02291: нарушено ограничение целостности (ADMIN_BF.ENROLLMENT_STD_ID) — родительский ключ не найден
Ответ №1:
Ошибка, с которой вы столкнулись, достаточно очевидна. В таблице нет ученика 104
, поэтому вы не можете создать зависимую запись в enrollment
. Эта ошибка связана не с вашими триггерами, а с вашими данными.
Теперь давайте посмотрим на insert
инструкцию для этого конкретного пользователя:
INSERT INTO student values(104,'Sue','Williams','St.Cloud','MN',56301,'ACCT','SR',3.2,2386.55);
Вы пытаетесь ввести баланс 2386.55
. Но ваш триггер UNPAID_BALANCE
предотвращает превышение балансов 500
, что insert
приводит к возникновению ошибки приложения «Ваш баланс слишком высок для регистрации», что является основной причиной проблемы. Вам нужно исправить эту вставку.
Примечание: в последней серии вставок скрывается еще одна проблема enrollments
. Триггер ENROLL_MAX
допускает только двух учащихся на одного OFFERNO
, но вы пытаетесь назначить трех учащихся для предложения 2203
, а также трех для предложения 2205
. Это вызовет ошибку приложения «ПРЕВЫШЕНИЕ ДОПУСТИМОГО ЧИСЛА УЧАЩИХСЯ».
Комментарии:
1. Должен ли я, возможно, изменить свой триггер, чтобы он работал после, а не до этого? Я хочу, чтобы эти триггеры были настроены так, как я их настроил.
2. У меня есть два бизнес-правила (триггера), одно из которых заключается в том, чтобы не разрешать учащимся с балансом в 500 долларов или более, а другое — не разрешать учащимся регистрироваться на занятия, если в классе больше определенной суммы (2). Итак, оба этих триггера работают правильно, но есть ли способ показать, что он работает правильно, не вызывая этих ошибок?
3. @Boooo402: проблема не в вашем коде триггера — они делают то, для чего предназначены. Проблема в ваших данных, которые нарушают бизнес-правила. Исправьте свои данные вместо этого.