В Postgres, как вы ограничиваете возможные значения для определенного столбца? - PullRequest
45 голосов
/ 31 августа 2011

Я хочу создать столбец element_type в таблице (называемый discussion), который допускает текстовые значения «урок» или «викторина», но при этом выдает ошибку, если в этот столбец вставляется любое другое значение.

Я понимаю, что мог бы создать отдельную таблицу с именем element_types со столбцами element_id (первичный ключ, int) и element_type (уникальный, текстовый) и создать внешний ключ foreign_element_id в таблице discussion ссылка на столбец element_types element_id.Или, в качестве альтернативы, я мог бы вообще забыть element_id и просто установить element_type в качестве первичного ключа.Но я хочу избежать создания новой таблицы.

Существует ли более простой способ ограничения возможных значений в столбце без создания новой таблицы?

Ответы [ 3 ]

76 голосов
/ 31 августа 2011

Вы можете добавить CHECK CONSTRAINT:

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

Хотя ИМО более чистым вариантом будет создание ENUM:

CREATE TYPE element_type AS ENUM ('lesson', 'quiz');
29 голосов
/ 13 июля 2016

Сокращенный синтаксис:

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) )

Наслаждайся; -)

2 голосов
/ 31 августа 2011

Этот триггер генерирует исключение всякий раз, когда кто-то пытается вставить или обновить строку с недопустимым 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();

Если вы хотите удалить жестко запрограммированные типы, вы можете адаптировать его, чтобы проверить, если новыйтип существует в таблице типов.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...