在数据已经不正确的 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();
不过你真的应该再考虑一下。问问自己是否真的想要旧数据违规条件。清理旧的和错误的数据可能比保留它更好。否则你永远无法确定一行是否满足条件。
PostgreSQL 无法区分旧行和新行,因此您无法获得仅允许旧行违规的约束。
如其他答案中所述,如果您创建约束,则会检查现有行的有效性。
有一个例外允许您在包含违反条件的行的 table 上创建 CHECK
约束:将约束创建为 NOT VALID
。然后不会检查现有行的合规性。
但是,如开头所说,只有新行版本满足条件,才允许修改旧行。
另一种想法是添加类型为 boolean
的新列 old
以区分旧行和新行。然后你可以在检查条件中显式地排除旧行。
这对我来说似乎是一个有用的问题,并且在任何地方都找不到任何关于它的书面信息,所以我认为这可能太明显了。只是想确认一下:
如果我改变一个 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();
不过你真的应该再考虑一下。问问自己是否真的想要旧数据违规条件。清理旧的和错误的数据可能比保留它更好。否则你永远无法确定一行是否满足条件。
PostgreSQL 无法区分旧行和新行,因此您无法获得仅允许旧行违规的约束。
如其他答案中所述,如果您创建约束,则会检查现有行的有效性。
有一个例外允许您在包含违反条件的行的 table 上创建 CHECK
约束:将约束创建为 NOT VALID
。然后不会检查现有行的合规性。
但是,如开头所说,只有新行版本满足条件,才允许修改旧行。
另一种想法是添加类型为 boolean
的新列 old
以区分旧行和新行。然后你可以在检查条件中显式地排除旧行。