Триггеры работают корректно, но вызывают ошибку приложения, вызывающую некоторые ошибки с операторами insert

#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: проблема не в вашем коде триггера — они делают то, для чего предназначены. Проблема в ваших данных, которые нарушают бизнес-правила. Исправьте свои данные вместо этого.