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

Sql 在Postgres中,如何限制特定列的可能值?,sql,postgresql,Sql,Postgresql,我想在表(称为讨论)中创建一列元素类型,该列允许文本值“lesson”或“quick”,但如果在该列中插入任何其他值,则将生成错误 我知道我可以创建一个名为element\u-types的单独表,其中包含列element\u-id(主键,int)和element\u-type(唯一,文本)并在表讨论引用元素类型的列元素id中创建一个外键外键元素id。或者,我可以完全忘记element\u id,只将element\u type设置为主键。但我希望避免创建新表 有没有更直接的方法来限制列中可能的值

我想在表(称为
讨论
)中创建一列
元素类型
,该列允许文本值“lesson”或“quick”,但如果在该列中插入任何其他值,则将生成错误

我知道我可以创建一个名为
element\u-types
的单独表,其中包含列
element\u-id
(主键,int)和
element\u-type
(唯一,文本)并在表
讨论
引用
元素类型
的列
元素id
中创建一个外键
外键元素id
。或者,我可以完全忘记
element\u id
,只将
element\u type
设置为主键。但我希望避免创建新表

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

您可以添加

虽然IMO的清洁选项是创建一个:


每当有人试图插入或更新元素类型无效的行时,此触发器就会引发异常

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();
如果要删除硬编码类型,可以调整它以检查类型表中是否存在新类型。

shorcut语法为:

ALTER TABLE distributors  
   ADD CONSTRAINT check_types 
   CHECK (element_type IN ('lesson', 'quiz') );
这自动转换为:

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

享受;-)

为什么要避免创建表?它们并不特别昂贵,与其说是一张桌子的成本,还不如说是不必要的杂乱,只要我想限制可能的值,这在我的例子中是非常常见的。非常感谢。作为对其他可能和我一样不熟悉Postgres的人的一个提醒,CREATE TYPE创建了一个用户定义的类型,可以像使用int或text这样的任何其他类型一样使用。在本例中,可以说:
createtype元素_TYPE为ENUM('lesson','quick');创建表格讨论(元素类型的类型)值得注意的是,尽管您可以在最新版本中向枚举类型添加值,但没有优雅/简单的方法可以删除它们。如果您预期允许的值会发生很大变化,我建议使用检查约束。与检查约束或枚举相比,这是一个非常缓慢和复杂的解决方案。
ALTER TABLE distributors  
   ADD CONSTRAINT check_types 
   CHECK (element_type IN ('lesson', 'quiz') );
CONSTRAINT check_types CHECK (element_type::text = ANY (ARRAY['lesson'::character varying, 'quiz'::character varying) )