Oracle
 sql >> Base de Dados >  >> RDS >> Oracle

Usando subconsulta em uma instrução Check no Oracle


Existem três maneiras básicas de resolver esse tipo de problema, pois as restrições CHECK não podem ser baseadas em uma consulta.

Opção 1:acionadores

A abordagem mais simplista seria colocar um gatilho em TANK que consulta TANKS e lança uma exceção se o LEVEL exceder CAPACITY. O problema com esse tipo de abordagem simplista, porém, é que é quase impossível lidar com problemas de simultaneidade corretamente. Se a sessão 1 diminuir a CAPACITY, a sessão 2 aumentará o LEVEL e, em seguida, ambas as transações forem confirmadas, os gatilhos não poderão detectar a violação. Isso pode não ser um problema se uma ou ambas as tabelas raramente forem modificadas, mas em geral será um problema.

Opção 2:visualizações materializadas

Você pode resolver o problema de simultaneidade criando uma visão materializada ON COMMIT que une a tabela TANK e TANKS e, em seguida, criando uma restrição CHECK na visão materializada que verifica se o LEVEL <=CAPACITY. Você também pode evitar armazenar os dados duas vezes fazendo com que a visualização materializada contenha apenas dados que violariam a restrição. Isso exigirá logs de visualização materializados em ambas as tabelas base, o que adicionará um pouco de sobrecarga às inserções (embora menos do que usar gatilhos). Empurrar a verificação para o tempo de confirmação resolverá o problema de simultaneidade, mas apresenta um pouco de problema de gerenciamento de exceção, pois a operação COMMIT agora pode falhar porque a atualização da visualização materializada falhou. Seu aplicativo precisaria ser capaz de lidar com esse problema e alertar o usuário sobre esse fato.

Opção 3:alterar o modelo de dados

Se você tem um valor na tabela A que depende de um limite na tabela B, isso pode indicar que o limite em B deve ser um atributo da tabela A (em vez de ou além de ser um atributo da tabela B). Depende das especificidades do seu modelo de dados, é claro, mas geralmente vale a pena considerar.