SQL触发器不起作用

时间:2013-03-16 19:06:29

标签: sql postgresql triggers plpgsql

CREATE TABLE lab7.standings
(
    team_name    VARCHAR(100) NOT NULL PRIMARY KEY,
    wins         INTEGER,
    losses       INTEGER,
    winPct       NUMERIC,
    CHECK(wins > 0),
    CHECK(losses >0)
);

CREATE OR REPLACE FUNCTION
calc_winning_percentage()
RETURNS trigger AS $$
BEGIN
    New.winPct := New.wins /(New.wins + New.losses);
    RETURN NEW;
END;
$$LANGUAGE plpgsql;

CREATE TRIGGER
update_winning_percentage
AFTER INSERT OR UPDATE ON standings
FOR EACH ROW EXECUTE PROCEDURE calc_winning_percentage();

这准确地更新了我的排名表中的胜利,但似乎没有发送我新计算的胜率。

2 个答案:

答案 0 :(得分:2)

试试这个:

CREATE TRIGGER update_winning_percentage
BEFORE INSERT OR UPDATE ON standings
FOR EACH ROW EXECUTE PROCEDURE calc_winning_percentage();

答案 1 :(得分:2)

除了将触发器更改为BEFORE之外的integer

我注意到表定义中的三个事物:

1. numericwins

losseswinPct的类型为pointed out by @Grijesh,但SELECT 1 / 4, 2 / 4 integer

尝试以下方法:

0

两次都给你integer。结果类型为integer,小数位截断为零。在 numeric结果被强制转换为wins之前,您的触发器函数会发生这种情况。因此,lossesnumeric中仅影响小数位的更改会丢失到结果中。修复此问题:

..将基本表格中所有相关列的列定义更改为NEW.winPct := NEW.wins::numeric / (NEW.wins + NEW.losses);
..或更改触发功能:

numeric

将计算中的一个数字投射到::numericnumeric)会强制结果为integer并保留小数位数。

强烈建议 第二个变体,因为wins显然是lossesNEW.winPct := NEW.wins::float8 / (NEW.wins + NEW.losses);的正确类型。如果您的百分比不必非常精确,我还会考虑使用普通numeric作为百分比。然后您的触发器可以使用:

winPct

2.未加引号的列名winpct

它被转换为小写,实际上只是lab7.standings。请务必阅读floating point type (real or double precision)

3。模式

您的表格显然属于非标准架构:search_path。除非... BEFORE INSERT OR UPDATE ON lab7.standings ...中包含该内容,否则触发器创建必须使用模式限定名称:

{{1}}

P.S。

显示使用此类问题发布表定义的重要性。