Используя Oracle 11g, я пытаюсь получить последний символ названия курса с помощью триггера, а затем, в зависимости от последнего символа, он присваивает ученику оценку.
Я пробовал несколько разных подходов к проблеме, я получаю несколько разных ошибок, что вызывает у меня головную боль. Я не уверен, что я неправильно приближаюсь к курсору или вся проблема.
INSERT INTO GRADES (STUDNETID, SECTIONID, SECTIONINFO, COURSEID,COURSENAME, GRADE) VALUES (234501,153, '078',256877 , 'Intro to Holographic',"") ;
INSERT INTO GRADES (STUDNETID, SECTIONID, SECTIONINFO, COURSEID,COURSENAME, GRADE) VALUES (234519,153, '078',256877 ,'Intro to Holographic' ,"") ;
INSERT INTO GRADES (STUDNETID, SECTIONID, SECTIONINFO, COURSEID,COURSENAME ,GRADE) VALUES (234505,153, '078',256877 ,'Intro to Holographic', "") ;
INSERT INTO GRADES (STUDNETID, SECTIONID, SECTIONINFO, COURSEID,COURSENAME, GRADE) VALUES (23405,21, '012A',23532 ,'Starfleet Intro', "") ;
INSERT INTO GRADES (STUDNETID, SECTIONID, SECTIONINFO, COURSEID,COURSENAME, GRADE) VALUES (23419,21, '012A',23532 ,'Starfleet Intro', "") ;
INSERT INTO GRADES (STUDNETID, SECTIONID, SECTIONINFO, COURSEID,COURSENAME, GRADE) VALUES (23401,21, '012A',23532 ,'Starfleet Intro', "") ;
INSERT INTO GRADES (STUDNETID, SECTIONID, SECTIONINFO, COURSEID,COURSENAME, GRADE) VALUES (23418,21, '012A',23532 ,'Starfleet Intro', "") ;
INSERT INTO GRADES (STUDNETID, SECTIONID, SECTIONINFO, COURSEID,COURSENAME, GRADE) VALUES (234520,933,'278',843234 ,'Borg Technolgy', "");
INSERT INTO GRADES (STUDNETID, SECTIONID, SECTIONINFO, COURSEID,COURSENAME, GRADE) VALUES (234505,933,'278',843234 ,'Borg Technolgy' ,"");
INSERT INTO GRADES (STUDNETID, SECTIONID, SECTIONINFO, COURSEID,COURSENAME, GRADE) VALUES (234501,933,'278',843234 ,'Borg Technolgy' ,"");
INSERT INTO GRADES (STUDNETID, SECTIONID, SECTIONINFO, COURSEID, COURSENAME,GRADE) VALUES (234519,438,'531',542303 , 'Intro to Genetics',"");
create or replace TRIGGER gradeTrigger
AFTER Update ON Grade For Each Row
declare
cursor courseTitle_cur IS
select g.COURSENAME
from Grade g;
lastChar String (1);
gradeLetter String(1);
BEGIN
for courseTitle_cur in CourseName
loop
SubStr(CourseName, -1):= lastChar;
end loop;
If(lastChar = 'A' OR lastChar ='B'OR lastChar = 'C' OR lastChar = 'D' OR lastChar = 'E'OR lastChar = 'F') THEN
gradeLetter := "A";
ELSIF(lastChar = 'G'OR lastChar = 'H'OR lastChar = 'I'OR lastChar = 'J'OR lastChar = 'K')THEN
gradeLetter := "B";
ELSIF (LASTCHAR = 'L'or LASTCHAR = 'M'or LASTCHAR = 'N'or LASTCHAR = 'O'or LASTCHAR = 'P')then
gradeLetter := "C";
ELSIf (LASTCHAR = 'Q' OR LASTCHAR = 'R'OR LASTCHAR = 'S'OR LASTCHAR = 'T')THEN
gradeLetter := "D";
ELSIf (lastChar = 'U' OR lastChar ='V'OR lastChar = 'W'OR lastChar = 'X'OR lastChar = 'Y' OR lastChar = 'Z')THEN
gradeLetter := "E";
Return gradeLetter;
end if ;
End;
Я получаю такие ошибки, как "Ошибка (16,2): PL/SQL: оператор игнорируется" или "Ошибка (4,10): PL/SQL: ORA-00904: "G"."COURSENAME": недопустимый идентификатор" Это очень расстраивает, потому что я не могу точно определить, почему его игнорируют или он недействителен.
@BobJarvis Я отредактировал сообщение, указав то, что я вставляю в таблицу. Спасибо за совет по строковым ограничениям в PL/SQL.
Согласно вашему редактированию, таблица называется GRADES, а не GRADE. Кроме того, название поля — GRADE, а не GRADELETTER. Вы можете попробовать сделать эти замены и посмотреть, будет ли работать лучше.





Я думаю, вы неправильно поняли, как работают триггеры в Oracle.
Каждая обновляемая строка имеет состояние «до» и «после» — они представлены записями :old и :new соответственно.
Если вы хотите указать, как должно выглядеть значение поля после применения обновления, вам необходимо изменить поле в записи :newдо при применении обновления.
Поэтому я думаю, что ваш триггер, вероятно, должен выглядеть примерно так:
CREATE OR REPLACE TRIGGER grade_trigger
BEFORE INSERT OR UPDATE ON grades
FOR EACH ROW
BEGIN
IF substr(upper(:new.coursename), -1) IN ('A', 'B', 'C', 'D', 'E', 'F')
THEN
:new.grade := 'A';
ELSIF substr(upper(:new.coursename), -1) IN ('G', 'H', 'I', 'J', 'K')
THEN
:new.grade := 'B';
ELSIF substr(upper(:new.coursename), -1) IN ('L', 'M', 'N', 'O', 'P')
THEN
:new.grade := 'C';
ELSIF substr(upper(:new.coursename), -1) IN ('Q', 'R', 'S', 'T')
THEN
:new.grade := 'D';
ELSIF substr(upper(:new.coursename), -1) IN ('U', 'V', 'W', 'X', 'Y', 'Z')
THEN
:new.grade := 'E';
END IF;
END grade_trigger;
/
а вот доказательство того, что это работает.
Oracle выдает мне ошибку о плохой привязке, также я чувствую, что должен использовать курсор для этого @Boneist
@Boneist: глядя на недавнее редактирование вопроса OP, кажется, что имя таблицы GRADES, а не GRADE. Кроме того, название поля — GRADE, а не GRADELETTER. К черту эти придирчивые тупые компьютеры..! :-)
@Starfire Я обновил свой ответ и дал вам демонстрацию рабочего триггера. Как вы думаете, зачем нужен курсор? Это кажется плохим — зачем вам обновлять всю таблицу каждый раз, когда вы обновляете каждую строку?
@Boneist Я думал, что мне понадобится курсор для просмотра записей. Теперь, когда я вижу, как он работает, я вижу, что функция ДЛЯ КАЖДОЙ СТРОКИ покрывает это.
Мы не знаем, как выглядят ваши столы. Пожалуйста, отредактируйте свой вопрос и включите структуру ваших таблиц GRADE и COURSENAME, включая все имена полей и типы данных. Спасибо. А пока: в PL/SQL нет типа данных String. Используйте VARCHAR2(x). Строковые константы в PL/SQL следует заключать в одинарные, а не в двойные кавычки. Вы не можете присвоить значение функции, такой как SUBSTR. И триггеры не имеют возвращаемого значения.