Alguns comentários sobre o DDL que você postou.
- Não há
AUTOINCREMENT
palavra-chave no Oracle. Você precisaria criar uma sequência (geralmente uma sequência por tabela) e usar oNEXTVAL
da sequência noINSERT
própria instrução ou em um gatilho para preencher a chave primária sintética. - Não há nada que esteja criando um
VENUE_NO
coluna emEVENT_DETAILS
. Presumo que seu DDL real esteja definindo essa coluna.
Você não pode impor isso através de um simples
CHECK
restrição. Você pode criar um gatilho CREATE OR REPLACE TRIGGER validate_capacity
BEFORE INSERT OR UPDATE ON event_details
FOR EACH ROW
DECLARE
l_venue_capacity venue.capacity%type;
BEGIN
SELECT capacity
INTO l_venue_capacity
FROM venue
WHERE venue_no = :new.venue_no;
IF( l_venue_capacity < :new.no_players )
THEN
RAISE_APPLICATION_ERROR( -20001, 'Sorry, the venue has insufficient capacity' );
END IF;
END;
Esteja ciente, no entanto, que
- Você também precisaria ter um acionador no
VENUE
tabela que verifica se as alterações na capacidade do local fazem com que determinados eventos se tornem inválidos. Geralmente, isso exigiria que houvesse algum tipo de data na tabela de detalhes do evento, pois, presumivelmente, a capacidade de um local pode mudar com o tempo e você realmente deseja que a validação verifique apenas eventos futuros nesse local. - As soluções baseadas em gatilho nem sempre funcionam em ambientes multiusuário. Imagine que o local 1 tenha uma capacidade de 30. Agora, a sessão A atualiza essa capacidade para 15. Mas antes da sessão A ser confirmada, a sessão B insere um evento com um
NO_PLAYERS
de 20. Nenhum acionador de sessão verá um problema, portanto, ambas as alterações serão permitidas. Mas assim que ambas as sessões forem confirmadas, haverá um evento reservado com 20 jogadores em um local que suporta apenas 15 jogadores. O acionador emEVENT_DETAILS
poderia bloquear a linha noVENUE
table para evitar essa condição de corrida, mas você está serializando inserções e atualizações noEVENT_DETAILS
table, o que pode ser um problema de desempenho, especialmente se seu aplicativo sempre aguardar a entrada humana antes de confirmar uma transação.
Como alternativa aos gatilhos, você pode criar um
ON COMMIT
visão materializada que une as duas tabelas e coloca um CHECK
restrição nessa visão materializada que impõe a exigência de que o número de jogadores não pode exceder a capacidade do local. Isso funcionará em um ambiente multiusuário, mas requer logs de visualização materializados em ambas as tabelas base e move a verificação para o ponto em que as sessões são confirmadas, o que pode ser um pouco complicado. A maioria dos aplicativos não considera a possibilidade de um COMMIT
pode falhar, portanto, lidar com essas exceções pode ser complicado. E do ponto de vista da interface do usuário, pode ser um pouco complicado explicar ao usuário qual é o problema, pois a exceção pode estar relacionada a alterações feitas muito mais cedo na transação.