Un paio di commenti sul DDL che hai pubblicato.
- Non esiste
AUTOINCREMENTparola chiave in Oracle. Dovresti creare una sequenza (generalmente una sequenza per tabella) e utilizzare ilNEXTVALdalla sequenza inINSERTistruzione stessa o in un trigger per popolare la chiave primaria sintetica. - Non c'è niente che stia creando un
VENUE_NOcolonna 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
VENUEtabella 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_PLAYERSdi 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_DETAILSpotrebbe potenzialmente bloccare la riga inVENUEtabella per evitare questa race condition ma stai serializzando inserti e aggiornamenti suEVENT_DETAILStabella 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.