Et par kommentarer til den DDL, du sendte.
- Der er ingen
AUTOINCREMENT
nøgleord i Oracle. Du skal oprette en sekvens (generelt én sekvens pr. tabel) og brugeNEXTVAL
fra sekvensen enten iINSERT
sætningen selv eller i en trigger for at udfylde den syntetiske primærnøgle. - Der er intet, der skaber en
VENUE_NO
kolonne iEVENT_DETAILS
. Jeg antager, at din faktiske DDL definerer den kolonne.
Du kan ikke håndhæve dette gennem en simpel CHECK
begrænsning. Du kan oprette en trigger
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;
Vær dog opmærksom på, at
- Du skal også have en trigger på
VENUE
tabel, der kontrollerer, om ændringer i spillestedets kapacitet forårsager, at visse begivenheder bliver ugyldige. Generelt vil det kræve, at der er en slags dato i tabellen med begivenhedsdetaljer, da kapaciteten for et spillested formentlig kan ændre sig over tid, og du egentlig kun ønsker, at valideringen skal tjekke for fremtidige begivenheder i det pågældende sted. - Triggerbaserede løsninger vil ikke altid fungere i flerbrugermiljøer. Forestil dig, at mødested 1 har en kapacitet på 30. Nu opdaterer session A denne kapacitet til 15. Men før session A forpligtes, indsætter session B en begivenhed med en
NO_PLAYERS
af 20. Ingen af sessionernes trigger vil se et problem, så begge ændringer vil være tilladt. Men når begge sessioner forpligter sig, vil der være en begivenhed booket med 20 spillere på et sted, der kun understøtter 15 spillere. Udløseren påEVENT_DETAILS
kunne potentielt låse rækken iVENUE
tabel for at undgå denne løbstilstand, men du er ved at serialisere inserts og opdateringer påEVENT_DETAILS
tabel, som kan være et ydeevneproblem, især hvis din applikation nogensinde venter på menneskelige input, før den udfører en transaktion.
Som et alternativ til triggere kan du oprette en ON COMMIT
materialiseret visning, der forbinder de to tabeller og sætter en CHECK
begrænsning af det materialiserede synspunkt, der håndhæver kravet om, at antallet af spillere ikke må overstige spillestedets kapacitet. Det vil fungere i et miljø med flere brugere, men det kræver materialiserede visningslogfiler på begge basistabeller, og det flytter afkrydsningsfeltet til det punkt, hvor sessionerne commit, hvilket kan være en smule vanskeligt. De fleste programmer overvejer ikke muligheden for, at en COMMIT
erklæring kan mislykkes, så det kan være vanskeligt at håndtere disse undtagelser. Og fra et brugergrænsefladesynspunkt kan det være lidt vanskeligt at forklare brugeren, hvad problemet er, da undtagelsen kan relatere sig til ændringer foretaget meget tidligere i transaktionen.