2013-02-07 24 views
10

私はPostgreSQL 9.2を使用しており、カラムに条件付き制約を追加する必要があります。基本的には、他の2つの列にある値があるときに列が偽であることを確認したい。Postgres 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 

例:GIDは1とレルム= nodeaccess_ridあるとき、これが行うことになっている何

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

grant_updateが0に等しいことを確認しています。しかし、私が思うよりもむしろ、すべての列をこれらの値に似せるようにしています。本質的には、grant_updateが常に0、gidが常に1、レルムが常にnodeaccess_ridであることを確認しようとしています。私が手にエラーがある:

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

EDIT

私は、これは、更新時に起動されます機能する必要があるとしていると思います。

EDIT

私は上記の質問に行を追加して、その結果、以下のコメントで承認されたソリューションを更新しました。

+0

'int_unsigned'とは' Postgresの中に存在しないタイプsmallint_unsigned'です。あなたの質問をきれいにしてください。 –

+0

存在しないかどうかは、データベースのロールアップ方法です。その問題は正当なものです。 – thepriebe

答えて

15

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 
+0

私は私の質問に含まれていない側面を組み込むためにあなたのソリューションを少し変更しました。ユーザーや匿名ユーザーがページを更新できるようにする追加の属性があります。 – thepriebe

+0

実際のソリューションは次のようになりました。 'alter table if exists node_access add constraint chk_block_anonymous_page_edit check(これは次のようになります:check(gid <> 1 realm <> 'nodeaccess_rid' OR grant_update = 0 OR grant_delete = 0) ' – thepriebe

+0

私はあなたがこの制約のために' grant_update' *または* 'grant_delete'が' 0'になることを承知していると思いますが、この場合、 '' grant_update''または '' grant_delete''は '' grant_delete =必ずしも両方である必要はない。 –

3

これをトリガとして書きます。これにより、エラーを発生させたり、問題を処理したり、gid = 1、realm = 'nodeaccess_rid'を設定すると、エラーを発生させる可能性があります。

0

トリガー機能付き。これにより、役割をチェックし、ブール値フィールド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(); 
関連する問題