Você gosta de ir ao cinema? Você já considerou como é o design do banco de dados por trás do sistema de reservas? Neste artigo vamos preparar um modelo de banco de dados de exemplo para uma sala de cinema.
Existem algumas premissas que devemos ter em mente:
- os cinemas multiplex contemporâneos podem ter um ou mais auditórios dentro de um complexo maior,
- cada auditório pode ter um número diferente de assentos,
- os assentos são numerados com o número da fileira e a posição do assento dentro de uma fileira,
- um filme pode ter várias exibições em horários diferentes ou pode ser exibido simultaneamente em um auditório diferente,
- para cada exibição, um assento pode ser reservado/vendido apenas uma vez,
- queremos rastrear quem inseriu cada reserva/venda no sistema.
Vejamos um possível projeto de banco de dados para resolver este problema (o modelo foi criado com Vertabelo para banco de dados MySQL):
As descrições curtas da estrutura da tabela são fornecidas abaixo:
-
Omovie
tabela contém dados sobre os filmes que serão exibidos no cinema. A chave primária éid
, que é auto_incremented como todas as chaves primárias em todas as outras tabelas. O único dado obrigatório étitle
.
Todos os campos têm significados de acordo com seu nome. A colunaduration_min
pode ser usado para desabilitar a inserção de uma nova exibição ou para mostrar uma mensagem de alerta caso queiramos entrar em uma exibição em um auditório onde a triagem anterior ainda está em andamento:
previous screening start time + duration_min of it > this screening start time
-
Oauditorium
tabela identifica todos os auditórios no teatro. Todos os dados são obrigatórios.
Oseats_no
pode ser usado para calcular a porcentagem de disponibilidade de auditórios para uma exibição/filme/auditório/intervalo de data selecionados. Este é um exemplo de redundância de dados porque poderíamos obter o número de assentos para cada auditório contando-os noseat
tabela. Neste exemplo, pode não melhorar significativamente o desempenho. Mostro aqui como uma ideia que pode ajudar no desenho de modelos mais complexos. Se configurarmos o banco de dados dessa maneira, devemos ter em mente que, se alterarmos um dado, também teremos que alterar outros. Se adicionarmos ou excluirmos dados doseat
tabela temos que ajustar os valoresseats_no
noauditorium
tabela.
-
Ascreening
tabela contém dados de todas as triagens e todos os campos são obrigatórios. Uma exibição deve ter um filme, auditório e hora de início relacionados. Não podemos ter duas apresentações no mesmo auditório ao mesmo tempo. Podemos definir uma chave única que consiste emauditorium_id
escreening_start
. Esta configuração é melhor do que definir uma chave única que consiste emmovie_id
,auditorium_id
escreening_start
porque isso nos permitiria entrar em exibições de dois filmes diferentes ao mesmo tempo no mesmo auditório.
O código de visualização Vertabelo SQL para esta tabela se parece com isso (observe Screening_ak_1):
-- Tables -- Table screening CREATE TABLE screening ( id int NOT NULL AUTO_INCREMENT, movie_id int NOT NULL , auditorium_id int NOT NULL , screening_start timestamp NOT NULL , UNIQUE INDEX Screening_ak_1 (movie_id,auditorium_id,screening_start), CONSTRAINT Screening_pk PRIMARY KEY (id) );
-
Oseat
tabela contém uma lista de todos os assentos que temos em auditórios com cada assento atribuído estritamente a um auditório. Todos os campos são obrigatórios.
-
Oreservation_type
table é um dicionário de todos os tipos de reserva (por telefone, online, pessoalmente). Todos os campos são obrigatórios.
-
Oemployee
tabela lista todos os empregados que utilizam o sistema. Todos os campos são obrigatórios.
Em sistemas complexos, geralmente há mais funções, portanto, precisamos ter um dicionário de funções e uma conexão funcionário/função de usuário. Em nosso exemplo temos apenas um papel:a mesma pessoa insere reservas e vende ingressos.
-
Areservation
eseat_reserved
tabelas são as principais tabelas do nosso sistema. É por isso que eu os listei por último. Todas as outras tabelas podem existir sem tabelas de reserva, mas sem as tabelas de reserva perderíamos a razão de projetar todo o banco de dados em primeiro lugar.
Areservation
A tabela armazena dados sobre uma reserva e/ou venda de ingressos. Se tivermos uma reserva, o atributoreserved
seria definido como True, oreservation_type_id
seria definido de acordo com a origem da reserva e oemployee_reserved_id
conteria oid_employee
valor da pessoa que inseriu os dados (estaria vazio se a reserva tivesse sido feita online pelo cliente). Da mesma forma, se os ingressos foram vendidos, oemployee_paid_id
seria preenchido com oid_employee
valor da pessoa que vendeu os ingressos, o atributo pago seria definido como Verdadeiro. O atributo active identifica se um registro ainda é válido. Se os ingressos fossem vendidos, esse atributo sempre seria True e a reserva sem vendas ficaria ativa até 30 minutos antes do início da triagem
Oseat_reserved
mesa nos permite fazer uma reserva ou um pagamento para vários lugares. Depois que o funcionário verifica alguns assentos livres na interface, um registro seria adicionado a essa tabela para cada um deles. Se quisermos verificar quais assentos estão livres ou ocupados, podemos verificar os valores nesta tabela associada àreservation
tabela ondereservation.active = True
.
Vale a pena mencionar:
employee_reserved_id
não é obrigatório porque pode não existir reserva para um lugar (um bilhete para um lugar é vendido sem reserva prévia) ou é feito onlinereservation_type_id
é uma chave estrangeira que faz referência ao “id” do tipo de reserva. Não é obrigatório porque pode não existir uma reserva (caso tenhamos feito uma venda sem uma reserva prévia)reservation_contact
é um campo de entrada de texto para armazenar dados de uma pessoa que fez uma reserva, não é obrigatório porque uma reserva pode não existir (caso tenhamos feito uma venda sem uma reserva prévia)employee_paid_id
está relacionado a um usuário que fez uma venda, não é obrigatório porque uma venda pode não ter acontecido (assento foi reservado, a reserva foi cancelada automaticamente, o assento não foi vendido)paid
é um sinalizador que indica que o pagamento ocorreu e é obrigatório (os valores podem ser Sim/Verdadeiro ou Não/Falso)
No final, tenha em mente que ninguém gosta de encontrar outra pessoa em seu assento: