Ett par kommentarer om DDL du lagt upp.
- Det finns ingen
AUTOINCREMENTnyckelord i Oracle. Du måste skapa en sekvens (vanligtvis en sekvens per tabell) och användaNEXTVALfrån sekvensen antingen iINSERTeller i en trigger för att fylla i den syntetiska primärnyckeln. - Det finns inget som skapar en
VENUE_NOkolumnen 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å
VENUEtabell 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_PLAYERSav 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_DETAILSkan eventuellt låsa raden iVENUEtabell för att undvika detta tävlingstillstånd, men du serialiserar inlägg och uppdateringar påEVENT_DETAILStabell 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.