在Postgres中,如何限制特定列的可能值?

时间:2011-08-30 23:30:02

标签: sql postgresql

我想在表(称为element_type)中创建一个列discussion,该列允许文本值“lesson”或“quiz”,但如果在其中插入任何其他值,则会生成错误列。

我知道我可以使用列element_types(主键,int)和element_id(唯一,文本)创建一个名为element_type的单独表,并创建一个外键{{1在表foreign_element_id引用discussion的列element_types的表中。或者,我可以完全忘记element_id并将element_id设置为主键。但我想避免创建一个新表。

是否有更直接的方法来限制列中的可能值而不创建新表?

3 个答案:

答案 0 :(得分:76)

您可以添加CHECK CONSTRAINT:

ALTER TABLE distributors 
   ADD CONSTRAINT check_types 
   CHECK (element_type = 'lesson' OR element_type = 'quiz');

虽然IMO的清洁选项是创建ENUM

CREATE TYPE element_type AS ENUM ('lesson', 'quiz');

答案 1 :(得分:29)

shorcut语法是:

ALTER TABLE distributors  
   ADD CONSTRAINT check_types 
   CHECK (element_type IN ('lesson', 'quiz') );

这会将automaticolly转换为:

CONSTRAINT check_types CHECK (element_type::text = ANY (ARRAY['lesson'::character varying, 'quiz'::character varying) )

享受; - )

答案 2 :(得分:2)

只要有人试图插入或更新具有无效element_type的行,此触发器就会抛出异常。

CREATE OR REPLACE FUNCTION check_discussion_element_type() RETURNS TRIGGER AS $$
DECLARE new_element_type varchar(25);
BEGIN
    SELECT element_type into new_element_type
        FROM discussion
        WHERE discussion.element_id = NEW.element_id;

    IF new_element_type != 'lesson' AND new_element_type != 'quiz'
       THEN RAISE EXCEPTION 'Unexpected discussion type';
    END IF;
    RETURN NEW;
END;
$$ LANGUAGE plpgsql;
create trigger t_check_discussion_element_type after update or insert on discussion for each row execute procedure check_discussion_element_type();

如果要删除硬编码类型,可以对其进行调整以检查类型表中是否存在新类型。