I have two tables:
CREATE TABLE Event_details( event_no INTEGER AUTOINCREMENT NOT NULL,
no_players INTEGER NOT NULL,
game_type VARCHAR(20) NOT NULL,
payout_positions INTEGER NOT NULL,
PRIMARY KEY(event_no)
CONSTRAINT check_game_type CHECK(game_type IN ('NLH','NLO','PLO','PLH','STUD','HORSE')
CONSTRAINT check_no_players CHECK (no_players > 1)
CONSTRAINT check_payouts CHECK (payout_positions > 0 AND payout_positions < no_players));
CREATE TABLE Venue( venue_no INTEGER AUTOINCREMENT NOT NULL,
name VARCHAR(20) NOT NULL,
location VARCHAR(20) NOT NULL,
capacity INTEGER NOT NULL,
PRIMARY KEY (venue_no)
CONSTRAINT check_capacity CHECK (capacity > 0));
And a foreign key between them:
ALTER TABLE Event_details
ADD FOREIGN KEY (venue_no)
REFERENCES Venue(venue_no)
ON DELETE SET NULL;
I want to set up a CONSTRAINT (or TRIGGER???) that will not allow (or flag) an entry where Event_details(no_players) < Venue(capacity) where the Venue(capacity) is the value found in the foreign key row.
Is this possible?
A couple of comments on the DDL you posted.
AUTOINCREMENTkeyword in Oracle. You’d need to create a sequence (generally one sequence per table) and use theNEXTVALfrom the sequence either in theINSERTstatement itself or in a trigger to populate the synthetic primary key.VENUE_NOcolumn inEVENT_DETAILS. I assume your actual DDL is defining that column.You cannot enforce this through a simple
CHECKconstraint. You can create a triggerBe aware, however, that
VENUEtable that checks to see whether changes to the venue’s capacity causes certain events to become invalid. Generally, that would require that there is some sort of date in the event details table since, presumably, the capacity of a venue can change over time and you really only want the validation to check for future events in that venue.NO_PLAYERSof 20. Neither session’s trigger will see a problem so both changes will be allowed. But once both sessions commit, there will be an event booked with 20 players in a venue that only supports 15 players. The trigger onEVENT_DETAILScould potentially lock the row in theVENUEtable to avoid this race condition but they you’re serializing inserts and updates on theEVENT_DETAILStable which could be a performance problem particularly if your application ever waits for human input before committing a transaction.As an alternative to triggers, you can create an
ON COMMITmaterialized view that joins the two tables together and put aCHECKconstraint on that materialized view that enforces the requirement that the number of players cannot exceed the venue capacity. That will work in a multi-user environment but it requires materialized view logs on both base tables and it moves the check to the point where the sessions commit which can be a bit tricky. Most applications don’t consider the possibility that aCOMMITstatement could fail so handling those exceptions can be tricky. And from a user-interface standpoint, it can be somewhat tricky to explain to the user what the problem is since the exception may relate to changes made much earlier in the transaction.