我在这张桌子上有“标记”
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
答案 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();
作为替代方案,我将使用如下的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;