【问题标题】:How in implement Triggers in Oracle如何在 Oracle 中实现触发器
【发布时间】:2019-09-19 16:20:24
【问题描述】:

使用 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”:无效标识符'之类的错误这非常令人沮丧,因为我无法确定它被忽略或无效的原因。

【问题讨论】:

  • 我们不知道你们的桌子是什么样子的。请编辑您的问题并包含您的 GRADE 和 COURSENAME 表的结构,包括所有字段名称和数据类型。谢谢。同时:PL/SQL 中没有字符串数据类型。使用 VARCHAR2(x)。 PL/SQL 中的字符串常量应该用单引号括起来,而不是双引号。您不能将值分配给函数,例如 SUBSTR。而且触发器没有返回值。
  • @BobJarvis 我用插入表格的内容编辑了帖子。感谢关于 PL/SQL 字符串约束的建议
  • 根据您的编辑,表的名称是GRADES,而不是GRADE。此外,该字段的名称是 GRADE,而不是 GRADELETTER。您可以尝试进行这些替换,看看效果是否更好。

标签: oracle triggers substring cursors


【解决方案1】:

我认为您误解了触发器在 Oracle 中的工作方式。

更新的每一行都有一个前后状态 - 这些分别由 :old:new 记录表示。

如果您想指定应用更新后字段的值应该是什么样子,您需要在应用更新之前更改:new记录中的字段。 p>

因此,我认为您的触发器应该类似于:

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;
/

这里是proof that it works

【讨论】:

  • Oracle 给我一个错误绑定错误,我也觉得我应该为这个@Boneist 使用游标
  • @Boneist:查看 OP 最近对该问题的编辑,似乎表的名称是 GRADES,而不是 GRADE。此外,该字段的名称是 GRADE,而不是 GRADELETTER。该死的这些挑剔的愚蠢计算机..! :-)
  • @Starfire 我已经更新了我的答案,并为您提供了一个工作触发器的演示。为什么你认为你需要一个光标?这似乎是一件坏事——为什么每次更新每一行时都要更新整个表?
  • @Boneist 我在想我需要一个游标来遍历记录。现在我看到它正在运行,我可以看到 FOR EACH ROW 函数涵盖了这一点
猜你喜欢
  • 2020-12-23
  • 2018-07-08
  • 2015-12-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-06-18
  • 2017-03-23
  • 2017-07-05
相关资源
最近更新 更多