Ein paar Kommentare zu der von Ihnen geposteten DDL.
- Es gibt kein
AUTOINCREMENT
Schlüsselwort in Oracle. Sie müssten eine Sequenz erstellen (im Allgemeinen eine Sequenz pro Tabelle) und denNEXTVAL
verwenden aus der Sequenz entweder imINSERT
-Anweisung selbst oder in einem Trigger, um den synthetischen Primärschlüssel zu füllen. - Es gibt nichts, was ein
VENUE_NO
schafft Spalte inEVENT_DETAILS
. Ich nehme an, Ihre tatsächliche DDL definiert diese Spalte.
Sie können dies nicht durch ein einfaches CHECK
erzwingen Zwang. Sie können einen Trigger erstellen
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;
Beachten Sie jedoch, dass
- Sie müssten auch einen Trigger auf
VENUE
haben Tabelle, die prüft, ob Änderungen an der Kapazität des Veranstaltungsortes dazu führen, dass bestimmte Veranstaltungen ungültig werden. Im Allgemeinen würde dies erfordern, dass die Tabelle mit den Veranstaltungsdetails eine Art Datum enthält, da sich die Kapazität eines Veranstaltungsortes vermutlich im Laufe der Zeit ändern kann und Sie wirklich nur möchten, dass die Validierung nach zukünftigen Veranstaltungen an diesem Veranstaltungsort sucht. - Triggerbasierte Lösungen funktionieren nicht immer in Umgebungen mit mehreren Benutzern. Stellen Sie sich vor, Veranstaltungsort 1 hat eine Kapazität von 30. Jetzt aktualisiert Sitzung A diese Kapazität auf 15. Aber bevor Sitzung A festgeschrieben wird, fügt Sitzung B ein Ereignis mit einem
NO_PLAYERS
ein von 20. Bei keinem der Trigger der Sitzung wird ein Problem angezeigt, sodass beide Änderungen zulässig sind. Aber sobald beide Sessions festgeschrieben sind, wird ein Event mit 20 Spielern an einem Ort gebucht, der nur 15 Spieler unterstützt. Der Trigger aufEVENT_DETAILS
könnte möglicherweise die Zeile imVENUE
sperren Tabelle, um diese Racebedingung zu vermeiden, aber Sie serialisieren Einfügungen und Aktualisierungen inEVENT_DETAILS
-Tabelle, was ein Leistungsproblem darstellen könnte, insbesondere wenn Ihre Anwendung jemals auf menschliche Eingaben wartet, bevor sie eine Transaktion festschreibt.
Als Alternative zu Triggern können Sie einen ON COMMIT
erstellen materialisierte Ansicht, die die beiden Tabellen zusammenfügt und ein CHECK
setzt Einschränkung dieser materialisierten Ansicht, die die Anforderung erzwingt, dass die Anzahl der Spieler die Kapazität des Veranstaltungsortes nicht überschreiten darf. Das funktioniert in einer Mehrbenutzerumgebung, erfordert aber materialisierte Ansichtsprotokolle für beide Basistabellen und verschiebt die Prüfung an den Punkt, an dem die Sitzungen festgeschrieben werden, was etwas schwierig sein kann. Die meisten Anwendungen berücksichtigen nicht die Möglichkeit, dass ein COMMIT
-Anweisung fehlschlagen, sodass die Behandlung dieser Ausnahmen schwierig sein kann. Und aus Sicht der Benutzeroberfläche kann es etwas schwierig sein, dem Benutzer das Problem zu erklären, da sich die Ausnahme auf Änderungen beziehen kann, die viel früher in der Transaktion vorgenommen wurden.