在数据已经不正确的 postgres table 中添加检查

Adding checks in postgres table where data is already incorrect

这对我来说似乎是一个有用的问题,并且在任何地方都找不到任何关于它的书面信息,所以我认为这可能太明显了。只是想确认一下:

如果我改变一个 postgres table 来添加一个检查,但是已经存在的数据与这个检查不一致,它不会发生任何事情,对吗?添加校验后Postgres只会校验inserted/updated的数据?

假设某行的出生年份列值为 1987。如果我添加一张出生年份 > 1990 的支票并且我不更新此字段但我更新此行中的其他字段会怎样。我可以更新这一行吗?如果没有,那么有没有办法添加检查,这样我就可以在没有检查的情况下更新所有旧行,但新添加的行会受到影响,基本上只在插入查询上添加检查而不是在更新查询上添加检查?希望我的问题清楚易懂。

检查约束会检查 table 中已有的值,如果有行违反条件则无法创建。这就是约束点,断言数据满足条件。

为了防止新数据违反条件,您可以做的是创建一个触发器来检查它并在违反时抛出错误。大致如下:

CREATE FUNCTION check_birthyear
                ()
                RETURNS TRIGGER
AS
$$
BEGIN
  IF NOT new.birthyear > 1990 THEN
    RAISE EXCEPTION 'birthyear must be greater than 1990';
  END IF;

  RETURN new;
END;
$$
LANGUAGE plpgsql;

CREATE TRIGGER elbat_check_birthyear
               BEFORE INSERT
               ON elbat
               FOR EACH ROW
               EXECUTE PROCEDURE check_birthyear();

db<>fiddle

不过你真的应该再考虑一下。问问自己是否真的想要旧数据违规条件。清理旧的和错误的数据可能比保留它更好。否则你永远无法确定一行是否满足条件。

PostgreSQL 无法区分旧行和新行,因此您无法获得仅允许旧行违规的约束。

如其他答案中所述,如果您创建约束,则会检查现有行的有效性。

有一个例外允许您在包含违反条件的行的 table 上创建 CHECK 约束:将约束创建为 NOT VALID。然后不会检查现有行的合规性。

但是,如开头所说,只有新行版本满足条件,才允许修改旧行。

另一种想法是添加类型为 boolean 的新列 old 以区分旧行和新行。然后你可以在检查条件中显式地排除旧行。