为什么我的 Postgres 触发器选择第一行的值并将其复制到其余条目中?

Why is my Postgres trigger selecting the first row's value and copying it into the rest entries?

我正在研究 PostgreSQL 触发器,我是新手, 我想开发一个 Postgres 触发器,在插入出生日期 (DOB) 时计算年龄,并将该日期与相应的 DOB 字段插入相同的 table.

下面是我的作品:

create or replace function Age() 
returns trigger as $body$
declare
dob1 date;
age1 integer;
BEGIN
select dob into dob1 from dateage; 
SELECT date_part('year', AGE(dob)) as "age", * FROM dateage into age1;
update dateage set age=age1;
return new;
END; $body$ language plpgsql;

这是我的函数调用

create trigger datea after insert on dateage
for each row execute procedure age();

我的 table 是这样的: name DATEAGE with attributes ID|出生日期 |年龄

当我插入 table 值时,第一行计算正常,但后续行中的年龄只是从第一行的年龄值复制而来。

感谢您提前做出的任何贡献。

不要插入或更新,只需计算值并分配它:

create or replace function Age() 
  returns trigger 
as 
$body$
BEGIN
  new.age := date_part('year', AGE(new.dob));
  return new;
END; 
$body$ language plpgsql;

然后将其用于 BEFORE 触发器:

create trigger datea 
  BEFORE insert on dateage
for each row execute procedure age();

回答“为什么从第一行开始复制”:

这一行:

select dob into dob1 from dateage; 

始终从 table 的 任意 行中检索 DOB(没有“第一行”开头这样的东西)。

当您 select 来自 table 的一行时(您不需要开始 - 见上文),您必须确保它检索到您刚刚插入的行通过添加 WHERE 条件:

select dob 
  into dob1 
from dateage
where pk_column = new.pk_column; 

年龄计算也不正确。您再次从 table 的 任意 行中 select 进行此操作 - 而不是刚刚插入的行。

但是因为您刚刚将 dob 值放入变量 dob1 中,所以不需要 运行 一个 SELECT 开始。

age1 := date_part('year', AGE(dob1));

最后,您还需要将 UPDATE 限制到您想要的行 - 再次添加 WHERE 条件:

update dateage 
  set age=age1
where pk_column = new.pk_column;

但这是一个非常糟糕的主意,因为明年这个信息就已经是错误的了。关系数据库中的一条经验法则是永远不要存储可以(轻松)从现有数据计算的信息。

使用该信息创建视图是一个更好的解决方案:

create view dates_with_age
as
select ..., dob, date_part('year', AGE(dob)) as dateage
from dateage;

这样您每次查询时都会在 dateage 列中获得准确(和正确)的值,而不仅仅是插入值后的第一年。