我是PostgreSQL的新手,非常喜欢约束如何与行级安全一起工作,但是我很困惑如何使它们做我想要的。
我有一个列,我想添加一个约束,为文本列创建一个最小长度,这个检查适用于:
(length((column_name):: text) > 6)
但是,它也会阻止用户更新任何column_name已经少于6个字符的行。
我想这样做,所以他们不能改变那个值,但仍然可以更新一行已经发生了,所以他们可以根据我的新策略根据需要改变它。
这可能吗?
但是,它也会阻止用户更新任何column_name已经少于6个字符的行。
嗯,没有。当您尝试添加CHECK
约束时,将检查所有现有行,如果发现任何违反将引发异常。
你必须让它成为NOT VALID
。是的。
你真的需要一个触发器检查新值的INSERT
或UPDATE
。没有那么便宜,也没有那么防弹,但仍然很结实。如:
CREATE OR REPLACE FUNCTION trg_col_min_len6()
RETURNS trigger
LANGUAGE plpgsql AS
$func$
BEGIN
IF TG_OP = 'UPDATE'
AND OLD.column_name IS NOT DISTINCT FROM NEW.column_name THEN
-- do nothing
ELSE
RAISE EXCEPTION 'New value for column "note" must have at least 6 characters.';
END IF;
RETURN NEW;
END
$func$;
-- trigger
CREATE TRIGGER tbl1_column_name_min_len6
BEFORE INSERT OR UPDATE ON tbl
FOR EACH ROW
WHEN (length(NEW.column_name) < 7)
EXECUTE FUNCTION trg_col_min_len6();
db<此处小提琴>此处小提琴>
直接向触发器检入WHEN
条件应该是最有效的。然后,触发器函数只在短值时调用,并且可以非常简单。
:
- 触发多个WHEN条件
- 更新列a或列b或列c时触发火灾
您可以为Insert和Update创建单独的触发器,让每个触发器完全定义何时触发。如果DML操作需要完全不同的逻辑,这种技术允许编写专用的触发器函数。在这种情况下,不需要触发函数减少到raise exception ...
。看到演示
-- Single trigger function for both Insert and Delete
create or replace function trg_col_min_len6()
returns trigger
language plpgsql
as $$
begin
raise exception 'Cannot % val = ''%''. Must have at least 6 characters.'
, tg_op, new.val;
return null;
end;
$$;
-- trigger before insert
create trigger tbl_val_min_len6_bir
before insert
on tbl
for each row
when (length(new.val) < 6)
execute function trg_col_min_len6();
-- trugger before update
create trigger tbl_val_min_len6_bur
before update
on tbl
for each row
when ( length(new.val) < 6
and new.val is distinct from old.val
)
execute function trg_col_min_len6();