Проектирование базы данных для маленьких на примере кинотеатра. Часть 4 - сеансы
В предыдущей части я остановился на планировании таблицы сеансов. Мне нужно было найти способ предотвратить создание пересекающихся по времени сеансов в одном зале. И в этом случае я решил воспользоваться ограничением EXCLUDE
предоставляемым PostgreSQL.
Кратко EXCLUDE
похож на UNIQUE
однако дает возможность использовать логику сложнее чем простое равенство. Например в нашем случае я воспользуюсь им для проверки не пересечения временных интервалов.
Помните в начале мы создали таблицу сеансов. Мне потребуется внести в нее небольшое изменение.
create table film_screenings ( id serial primary key, film int references films(id), -- фильм hall int references halls(id), -- кинозал start_at timestamp, -- дата и время начала сеанса recomended_price numeric -- рекомендованная цена билета ); -- удаляю столбец start_at alter table film_screenings drop column start_at; -- добавляю колонку screening_time типа tstzrange alter table film_screenings add column screening_time tstzrange;
В коде выше, я удалил колонку start_at
и вместо неё добавил screening_time
. Я решил использовать тип tstzrange
для того чтобы в одном поле хранить начало и конец сеанса. Кроме этого для данного типа можно воспользоваться ограничением EXCLUDE
что я и сделал.
alter table film_screenings add constraint no_screening_time_overlap exclude using gist ( screening_time WITH && -- check for overlapping ranges );
Давайте убедимся что ограничение работает:
insert into film_screenings (film, hall, recomended_price, screening_time) values (1, 1, 39.99, '["2023-01-01 19:00:00", "2023-01-01 20:45:00"]');
Попробуем внести строку с перекрытием:
insert into film_screenings (film, hall, recomended_price, screening_time) values (1, 1, 39.99, '["2023-01-01 20:45:00", "2023-01-01 23:00:00"]');
+==========================================================================================================================================================================================+ | insert into film_screenings (film, hall, recomended_price, screening_time) | | values (1, 1, 39.99, '["2023-01-01 20:45:00", "2023-01-01 23:00:00"]') | +==========================================================================================================================================================================================+ | ERROR: conflicting key value violates exclusion constraint "no_screening_time_overlap" | | DETAIL: Key (screening_time)=(["2023-01-01 20:45:00+00","2023-01-01 23:00:00+00"]) conflicts with existing key (screening_time)=(["2023-01-01 19:00:00+00","2023-01-01 20:45:00+00"]). | +------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
Таким образом мы гарантируем консистентность данных в таблице сеансов.
В следующем цикле статей мы рассмотрим базовый анализ данных нашего кинотеатра. А можете экперементировать в построении баз данных на SQLize.online