Det finns tre grundläggande sätt att lösa den här typen av problem eftersom CHECK-begränsningar inte kan baseras på en fråga.
Alternativ 1:Utlösare
Det mest förenklade tillvägagångssättet skulle vara att sätta en trigger på TANK som frågar TANKS och kastar ett undantag om LEVEL överskrider CAPACITY. Problemet med denna typ av förenklade tillvägagångssätt är dock att det är nästan omöjligt att hantera samtidighetsproblem korrekt. Om session 1 minskar KAPACITETEN, då ökar session 2 LEVEL, och sedan båda transaktionerna commit, kommer triggers inte att kunna upptäcka överträdelsen. Detta kanske inte är ett problem om en eller båda tabellerna sällan ändras, men i allmänhet kommer det att vara ett problem.
Alternativ 2:Materialiserade vyer
Du kan lösa samtidighetsproblemet genom att skapa en ON COMMIT materialiserad vy som förenar tabellen TANK och TANKS och sedan skapa en CHECK-begränsning på den materialiserade vyn som verifierar att LEVEL <=CAPACITY. Du kan också undvika att lagra data två gånger genom att låta den materialiserade vyn bara innehålla data som skulle bryta mot begränsningen. Detta kommer att kräva materialiserade vyloggar på båda bastabellerna vilket kommer att lägga till lite overhead till inlägg (men mindre än att använda triggers). Att trycka på kontrollen till commit-time kommer att lösa samtidighetsproblemet men det introducerar lite av ett undantagshanteringsproblem eftersom COMMIT-operationen nu kan misslyckas eftersom den materialiserade vynuppdateringen misslyckades. Din applikation skulle behöva kunna hantera det problemet och varna användaren om det.
Alternativ 3:Ändra datamodellen
Om du har ett värde i tabell A som beror på en gräns i tabell B, kan det tyda på att gränsen i B borde vara ett attribut för tabell A (istället för eller förutom att vara ett attribut i tabell B). Det beror naturligtvis på detaljerna i din datamodell, men det är ofta värt att överväga.