Un paio di commenti sul DDL che hai pubblicato.
- Non esiste
AUTOINCREMENT
parola chiave in Oracle. Dovresti creare una sequenza (generalmente una sequenza per tabella) e utilizzare ilNEXTVAL
dalla sequenza inINSERT
istruzione stessa o in un trigger per popolare la chiave primaria sintetica. - Non c'è niente che stia creando un
VENUE_NO
colonna inEVENT_DETAILS
. Presumo che il tuo attuale DDL stia definendo quella colonna.
Non puoi imporre questo tramite un semplice CHECK
vincolo. Puoi creare un 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;
Tieni presente, tuttavia, che
- Dovresti anche avere un attivatore su
VENUE
tabella che verifica se le modifiche alla capacità della sede causano l'annullamento di determinati eventi. In genere, ciò richiederebbe che ci sia una sorta di data nella tabella dei dettagli dell'evento poiché, presumibilmente, la capacità di una sede può cambiare nel tempo e in realtà vuoi solo che la convalida controlli gli eventi futuri in quella sede. - Le soluzioni basate su trigger non funzionano sempre in ambienti multiutente. Immagina che la sede 1 abbia una capacità di 30. Ora, la sessione A aggiorna tale capacità a 15. Ma prima che la sessione A si impegni, la sessione B inserisce un evento con un
NO_PLAYERS
di 20. Nessuno dei trigger di sessione vedrà un problema, quindi entrambe le modifiche saranno consentite. Ma una volta che entrambe le sessioni si impegnano, ci sarà un evento prenotato con 20 giocatori in una sede che supporta solo 15 giocatori. L'attivatore suEVENT_DETAILS
potrebbe potenzialmente bloccare la riga inVENUE
tabella per evitare questa race condition ma stai serializzando inserti e aggiornamenti suEVENT_DETAILS
tabella che potrebbe essere un problema di prestazioni, in particolare se l'applicazione attende l'input umano prima di eseguire una transazione.
In alternativa ai trigger, puoi creare un ON COMMIT
vista materializzata che unisce le due tabelle insieme e inserisce un CHECK
vincolo su quella visione materializzata che impone il requisito che il numero di giocatori non possa superare la capacità della sede. Funzionerà in un ambiente multiutente, ma richiede registri di visualizzazione materializzati su entrambe le tabelle di base e sposta il controllo al punto in cui le sessioni si impegnano, il che può essere un po' complicato. La maggior parte delle applicazioni non considera la possibilità che un COMMIT
istruzione potrebbe non riuscire, quindi gestire tali eccezioni può essere complicato. E dal punto di vista dell'interfaccia utente, può essere alquanto complicato spiegare all'utente qual è il problema poiché l'eccezione potrebbe riguardare modifiche apportate molto prima nella transazione.