创建检查约束时如何替换变量?

问题描述

我需要为新添加的行添加一个必填字段。但是,由于表很大,因此不希望为旧行设置认值。我需要提供一个自动脚本来执行此操作。 我试过了,但是不起作用:

do $$
declare 
    max_id int8;
begin
    select max(id) into max_id from transactions;
    alter table transactions add constraint check_process_is_assigned check (id <= max_id or process_id is not null);
end $$;

解决方法

诸如ALTER TABLE之类的实用程序命令不接受参数。仅基本DML命令SELECTINSERTUPDATEDELETE可以执行。 参见:

您需要动态SQL ,例如:

DO
$do$
BEGIN
   EXECUTE format(
     'ALTER TABLE transactions
      ADD CONSTRAINT check_process_is_assigned CHECK (id <= %s OR process_id IS NOT NULL)',(SELECT max(id) FROM transactions)
   );
END
$do$;

db 提琴here

这会基于 current 最大值CHECK创建一个id约束。

也许NOT VALID constraint会更好?不会针对现有行进行检查:

ALTER TABLE transactions
      ADD CONSTRAINT check_process_is_assigned CHECK (process_id IS NOT NULL) NOT VALID;

但是在这种情况下,您必须“修复”要更新的旧行。 (即,到目前为止,如果为process_id赋值为NULL。)请参阅: