1
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();

这准确地更新了我的积分表中的胜利,但似乎没有发送我新计算的获胜百分比。

4

2 回答 2

2

除了将触发器更改为BEFORE@Grijesh指出的那样

我在您的表定义中注意到三件事:

1.integer对比numeric

winslosses是 类型integer, 但winPctnumeric

尝试以下操作:

SELECT 1 / 4, 2 / 4

给你0两次。结果是类型的integer,小数位被截断为零。这发生在您的触发器函数中,然后在分配integer中强制执行结果。numeric因此,仅影响小数位的变化winslosses丢失在结果中。通过以下方式解决此问题:

.. 要么将列定义更改numeric为基表中所有涉及的列。
..或更改触发功能:

NEW.winPct := NEW.wins::numeric / (NEW.wins + NEW.losses);

将计算中的数字之一转换为numeric( ::numeric) 会强制结果为numeric并保留小数位数。

强烈建议使用第二个变体,因为integer显然是winsand的正确类型losses。如果您的百分比不必非常精确,我还会考虑使用普通浮点类型realdouble precision作为百分比。然后您的触发器可以使用:

NEW.winPct := NEW.wins::float8 / (NEW.wins + NEW.losses);

2.不带引号的列名winPct

它被转换为小写,实际上只是winpct. 请务必阅读PostgreSQL 中的标识符

3. 架构

您的表显然存在于非标准模式中:lab7.standings. 除非包含在您的 中search_path,否则触发器创建必须使用模式限定名称:

...
BEFORE INSERT OR UPDATE ON lab7.standings
...

附言

去展示用这种问题发布你的表定义的重要性。

于 2013-03-16T21:03:55.453 回答
2

尝试这个:

CREATE TRIGGER update_winning_percentage
BEFORE INSERT OR UPDATE ON standings
FOR EACH ROW EXECUTE PROCEDURE calc_winning_percentage();
于 2013-03-16T19:09:46.620 回答