Postgres 9.2 - 添加条件约束检查

时间:2013-02-07 20:59:06

标签: postgresql drupal constraints postgresql-9.2

我正在使用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'));

这应该做的是确保当gid为1且realm = nodeaccess_rid 时 grant_update等于0。但是,我认为不是做我想要的,而是试图让所有列都模仿这些值。本质上,它试图确保grant_update始终为0,gid始终为1,而realm始终为nodeaccess_rid。我得到的错误是:

ERROR:  check constraint "block_anonymous_page_edit" is violated by some row

修改

我认为这必须是一个在更新时触发的功能。

修改

我在上面的问题中添加了一行,然后通过以下评论更新了已批准的解决方案。

3 个答案:

答案 0 :(得分:17)

一旦你围绕逻辑思考它,这是一个相当简单的CHECK constraint

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

测试:

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

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

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

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

答案 1 :(得分:3)

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

答案 2 :(得分:0)

我最终选择了触发功能。这将检查角色并使用boolean-ish字段grant_update和grant_delete将不需要的功能设置为off。下面的函数也保留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();