表缺少FROM子句条目

时间:2019-07-17 08:34:50

标签: sql postgresql

我在这张桌子上有“标记”

id bigserial
name VARCHAR(50)
english, maths, science, sst int
status VARCHAR(10)
ID  | Name   | Maths | English | Science | SST  | Status

我想创建一个带有函数的触发器,以便每当我为学生插入或更新分数时,它都会计算该学生的分数平均值,如果该分数大于40%,则状态列应显示“通过“否则,表示该特定学生未通过。

功能:

marks=# CREATE OR REPLACE FUNCTION trigger() RETURNS TRIGGER AS $table$
marks$# BEGIN
marks$# IF (marks.science+marks.maths+marks.sst+marks.english)/400*100>40
marks$# THEN INSERT INTO marks (Status) VALUES ('Pass');
marks$# ELSE
marks$# INSERT INTO marks (Status) VALUES ('Fail');
marks$# END IF;
marks$# END;
marks$# $table$
marks-# language plpgsql;

触发:

marks=# CREATE TRIGGER trggr
marks-# AFTER INSERT ON marks
marks-# FOR EACH ROW
marks-# EXECUTE PROCEDURE trigger();

每当我尝试插入数据时,都会引发此错误:

marks=# INSERT INTO marks (name, english, maths, science, sst) VALUES ('Ziyan', 54, 63, 74, 85);
ERROR:  missing FROM-clause entry for table "marks"
LINE 1: SELECT (marks.science+marks.maths+marks.sst+marks.english)/4...
                ^
QUERY:  SELECT (marks.science+marks.maths+marks.sst+marks.english)/400*100>40
CONTEXT:  PL/pgSQL function trigger() line 3 at IF

1 个答案:

答案 0 :(得分:1)

您错过了代码中的几件事。

首先,您不能在INSERT触发器内的同一表上进行INSERT操作,因为它将无限级联插入。我认为您想要一个UPDATE,您可以简单地分配NEW.status而不是将其转换为BEFORE触发器。

如果您希望被触发的语句继续修改数据(RETURN NEW),则需要从触发器INSERT

第三,您要计算平均%标记的表达式不正确。应将100乘以分子。

请注意,插入的列不是使用tablename.columnname关键字引用的NEW。此外,我将函数名称更改为fn_trigger,而不是简单的trigger是关键字。

 CREATE OR REPLACE FUNCTION fn_trigger() RETURNS TRIGGER AS 
 $table$
 BEGIN
    IF 100*(NEW.science + NEW.maths + 
            NEW.sst + NEW.english )/400 > 40 THEN 

    NEW.Status =  'Pass'; 
    ELSE
      NEW.Status =  'Fail';
    END IF;

     RETURN NEW;
  END;
 $table$ language plpgsql;


 CREATE TRIGGER trggr
  BEFORE INSERT ON marks
   FOR EACH ROW
 EXECUTE PROCEDURE fn_trigger();

DEMO

作为替代方案,我将使用如下的View来满足此要求,而不是像有人更新标记那样使用触发器,还需要使用UPDATE触发器。

CREATE OR REPLACE View v_marks as 
 SELECT science ,maths ,english,sst, 
  CASE WHEN 100 * (science + maths + sst + english ) /400 > 40 
       THEN 'Pass' Else 'Fail'
  END as Status from marks;