Een paar opmerkingen over de DDL die je hebt gepost.
- Er is geen
AUTOINCREMENT
trefwoord in Oracle. U moet een reeks maken (meestal één reeks per tabel) en deNEXTVAL
gebruiken uit de reeks ofwel in deINSERT
statement zelf of in een trigger om de synthetische primaire sleutel in te vullen. - Er is niets dat een
VENUE_NO
aanmaakt kolom inEVENT_DETAILS
. Ik neem aan dat je werkelijke DDL die kolom definieert.
U kunt dit niet afdwingen met een simpele CHECK
beperking. U kunt een trigger maken
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;
Houd er echter rekening mee dat
- Je zou ook een trigger moeten hebben op de
VENUE
tabel die controleert of veranderingen in de capaciteit van de locatie ertoe leiden dat bepaalde evenementen ongeldig worden. Over het algemeen zou dat vereisen dat er een soort datum in de tabel met evenementdetails staat, aangezien vermoedelijk de capaciteit van een locatie in de loop van de tijd kan veranderen en je eigenlijk alleen wilt dat de validatie controleert op toekomstige evenementen op die locatie. - Op triggers gebaseerde oplossingen werken niet altijd in omgevingen met meerdere gebruikers. Stel je voor dat locatie 1 een capaciteit heeft van 30. Nu, sessie A werkt die capaciteit bij naar 15. Maar voordat sessie A zich commit, voegt sessie B een evenement in met een
NO_PLAYERS
van 20. De trigger van geen van beide sessies ziet een probleem, dus beide wijzigingen zijn toegestaan. Maar zodra beide sessies zijn vastgelegd, wordt er een evenement geboekt met 20 spelers op een locatie die slechts 15 spelers ondersteunt. De trigger opEVENT_DETAILS
kan mogelijk de rij in deVENUE
lock vergrendelen tabel om deze race-conditie te vermijden, maar ze serialiseren inserts en updates op deEVENT_DETAILS
tabel, wat een prestatieprobleem kan zijn, vooral als uw toepassing ooit wacht op menselijke input voordat een transactie wordt uitgevoerd.
Als alternatief voor triggers kunt u een ON COMMIT
. maken gematerialiseerde weergave die de twee tabellen samenvoegt en een CHECK
. plaatst beperking van die gematerialiseerde visie die de vereiste afdwingt dat het aantal spelers de capaciteit van de zaal niet mag overschrijden. Dat werkt in een omgeving met meerdere gebruikers, maar het vereist gematerialiseerde weergavelogboeken op beide basistabellen en het verplaatst de controle naar het punt waar de sessies worden vastgelegd, wat een beetje lastig kan zijn. De meeste toepassingen houden geen rekening met de mogelijkheid dat een COMMIT
statement kan mislukken, dus het omgaan met die uitzonderingen kan lastig zijn. En vanuit het oogpunt van de gebruikersinterface kan het wat lastig zijn om aan de gebruiker uit te leggen wat het probleem is, aangezien de uitzondering betrekking kan hebben op wijzigingen die veel eerder in de transactie zijn aangebracht.