PostgreSQL检查约束

时间:2012-04-05 10:47:47

标签: postgresql

CREATE TABLE my_table
(
    fk      INTEGER,
    field_1 INTEGER,
    field_2 INTEGER,
    field_3 INTEGER
)

VALID:

    fk    |    field_1    |    field_2    |    field_3              
----------+---------------+---------------+---------------
     1    |      1        |      null     |      null
     1    |      null     |      1        |      null
     1    |      null     |      null     |      1

有可能创建一个检查约束,它只允许1个3的字段对于1 fk不为空吗?

2 个答案:

答案 0 :(得分:2)

想到了直截了当的方式:

CHECK ((field_1 IS NOT NULL AND field_2 IS NULL AND field_3 IS NULL) OR
       (field_2 IS NOT NULL AND field_1 IS NULL AND field_3 IS NULL) OR
       (field_3 IS NOT NULL AND field_1 IS NULL AND field_2 IS NULL))

答案 1 :(得分:1)

目前还不太清楚你想要达到的目标。

如果每行只需要一列NOT NULL,那么Nitram的答案就可以了,您也可以尝试:

CHECK ((sign(coalesce(field_1,0)) +
        sign(coalesce(field_2,0)) + sign(coalesce(field_3,0))) <= 1)

否则,如果您需要在每个具有给定FK的行中只有一个NOT NULL列,您应该查看CONSTRAINT TRIGGER,如下所示:

CREATE OR REPLACE FUNCTION only_one() RETURNS trigger AS $only_one$
DECLARE
    cnt  int4;
BEGIN
    SELECT sign(coalesce(field_1,0)) +
           sign(coalesce(field_2,0)) +
           sign(coalesce(field_3,0)) +
           sign(coalesce(NEW.field_1,0)) +
           sign(coalesce(NEW.field_2,0))+
           sign(coalesce(NEW.field_3,0))
      INTO cnt
      FROM my_table WHERE fk = NEW.fk;

    IF cnt > 1 THEN
        RAISE EXCEPTION 'Sorry, too much NOT NULL values for FK=%', NEW.fk;
    END IF;

    RETURN NEW;
END;
$only_one$ LANGUAGE plpgsql;
CREATE CONSTRAINT TRIGGER my_table_only_one 
 AFTER INSERT OR UPDATE ON my_table
   FOR EACH ROW EXECUTE PROCEDURE only_one();