Ett par kommentarer om DDL du lagt upp.
- Det finns ingen
AUTOINCREMENT
nyckelord i Oracle. Du måste skapa en sekvens (vanligtvis en sekvens per tabell) och användaNEXTVAL
från sekvensen antingen iINSERT
eller i en trigger för att fylla i den syntetiska primärnyckeln. - Det finns inget som skapar en
VENUE_NO
kolumnen iEVENT_DETAILS
. Jag antar att din faktiska DDL definierar den kolumnen.
Du kan inte genomdriva detta genom en enkel CHECK
begränsning. Du kan skapa en utlösare
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;
Var dock medveten om att
- Du skulle också behöva ha en utlösare på
VENUE
tabell som kontrollerar om ändringar i lokalens kapacitet gör att vissa händelser blir ogiltiga. Generellt sett skulle det kräva att det finns något slags datum i evenemangsinformationstabellen, eftersom kapaciteten för en plats förmodligen kan förändras över tiden och du vill egentligen bara att valideringen ska kontrollera om det finns framtida evenemang i den platsen. - Triggerbaserade lösningar fungerar inte alltid i fleranvändarmiljöer. Föreställ dig att plats 1 har en kapacitet på 30. Nu uppdaterar session A den kapaciteten till 15. Men innan session A genomförs, infogar session B en händelse med en
NO_PLAYERS
av 20. Ingen av sessionernas utlösare kommer att se något problem så båda ändringarna kommer att tillåtas. Men när båda sessionerna har bestämt sig kommer det att finnas ett evenemang bokat med 20 spelare i en lokal som endast har stöd för 15 spelare. Utlösaren påEVENT_DETAILS
kan eventuellt låsa raden iVENUE
tabell för att undvika detta tävlingstillstånd, men du serialiserar inlägg och uppdateringar påEVENT_DETAILS
tabell som kan vara ett prestandaproblem, särskilt om din applikation någonsin väntar på mänsklig input innan den utför en transaktion.
Som ett alternativ till utlösare kan du skapa en ON COMMIT
materialiserad vy som sammanfogar de två tabellerna och sätter en CHECK
begränsning av den förverkligade uppfattningen som upprätthåller kravet att antalet spelare inte får överstiga spelplatsens kapacitet. Det kommer att fungera i en miljö med flera användare men det kräver materialiserade vyloggar på båda bastabellerna och det flyttar kontrollen till den punkt där sessionerna commit vilket kan vara lite knepigt. De flesta applikationer överväger inte möjligheten att en COMMIT
uttalande kan misslyckas så att hantera dessa undantag kan vara knepigt. Och ur användargränssnittssynpunkt kan det vara lite knepigt att förklara för användaren vad problemet är eftersom undantaget kan relatera till ändringar som gjorts mycket tidigare i transaktionen.