添加条件约束检查

问题描述 投票:0回答:3

我正在使用 PostgreSQL 9.2,需要在列上添加条件约束。本质上,我想确保当其他两列具有特定值时,一列为假。

表格定义:

gid          | int_unsigned           | not null default 0
realm        | character varying(255) | not null default ''::character varying
grant_update | smallint_unsigned      | not null default (0)::smallint
grant_delete | smallint_unsigned      | not null default (0)::smallint

例子:

alter table node_access add constraint block_anonymous_page_edit
check (grant_update = 0 WHERE (gid = 1 AND realm = 'nodeaccess_rid'));

这是假设确保

grant_update
gid
为1且
realm = nodeaccess_rid
时等于0。

但是,我认为与其做我想做的,不如说它实际上是在试图让所有的列都模仿这些值。本质上,它试图确保

grant_update
始终为 0,
gid
始终为 1,而
realm
始终为
nodeaccess_rid
。我得到的错误是:

错误:某些行违反了检查约束“block_anonymous_page_edit”

也许是在更新时触发的功能?

postgresql drupal constraints postgresql-9.2
3个回答
35
投票

一旦你围绕逻辑思考,这很简单

CHECK
约束

CREATE TABLE tbl (
  gid          int      NOT NULL DEFAULT 0
, realm        text     NOT NULL DEFAULT ''
, grant_update smallint NOT NULL DEFAULT 0
, CONSTRAINT block_anonymous_page_edit
  CHECK (gid <> 1 OR realm <> 'nodeaccess_rid' OR grant_update = 0)
);

测试:

-- these work:
INSERT INTO tbl(gid, realm, grant_update)
VALUES (1, 'nodeaccess_rid', 0);

INSERT INTO tbl(gid, realm, grant_update)
VALUES (1, 'some_string',    1);

INSERT INTO tbl(gid, realm, grant_update)
VALUES (2, 'nodeaccess_rid', 1);

-- check violation!
INSERT INTO tbl(gid, realm, grant_update)
VALUES (1, 'nodeaccess_rid', 1);

db<>小提琴这里


3
投票

我会把它写成触发器。这使您可以灵活地引发错误(可能使用可以最好地测试的自定义代码)或仅处理问题并在 gid=1 和 realm = 'nodeaccess_rid' 时设置 grant_update = 0


-2
投票

我最终选择了触发功能。这将检查角色并使用布尔型字段 grant_update 和 grant_delete 将不需要的功能设置为关闭。下面的函数还保留了 grant_view 值而不是覆盖它。

CREATE OR REPLACE function block_anonymous_page_edit()
RETURNS trigger AS $function$
BEGIN
  IF NEW.gid = 1 AND NEW.realm != 'nodeaccess_author' AND (NEW.grant_update = 1 OR NEW.grant_delete = 1) THEN
    RAISE WARNING 'Anonymous users are not allowed to edit pages.';
    NEW.grant_update := 0;
    NEW.grant_delete := 0;
  END IF;
  RETURN NEW;
END;
$function$ LANGUAGE plpgsql;

CREATE TRIGGER tgr_block_anonymous_page_edit BEFORE INSERT OR UPDATE ON node_access FOR EACH ROW EXECUTE PROCEDURE block_anonymous_page_edit();
© www.soinside.com 2019 - 2024. All rights reserved.