I have a small test database I’m using for learning SQL.
There’s a Duel table, which contains two Pilot foreign keys (the duelists). I want to check if the duelists haven’t already “met” before insertion.
Pseudocode:
before insertion on Duel
for each row already in the table
if ((new_row.numpilot1 = old_row.numpilot1 and new_row.numpilot2 = old_row.numpilot2) OR
(new_row.numpilot1 = old_row.numpilot2 and new_row.numpilot2 = old_row.numpilot1)
)
insertion fails
One other alternative would be
tempnum integer;
select numpilot1 into tempnum from duel
where (:NEW.numpilot1 = numpilot1 and :NEW.numpilot2 = numpilot2) OR
(:NEW.numpilot1 = numpilot2 and :NEW.numpilot2 = numpilot1);
if tempnum == null
fail insertion
What is the PL/SQL (Oracle DBMS) version of this?
Normally, you wouldn’t use a trigger for this sort of requirement. Instead, you’d create a couple of constraints on the table. I would suggest a unique constraint on (
numpilot1,numpilot2) along with a check constraint that ensures thatnumpilot1 < numpilot2.If you wanted to do this sort of thing in a trigger, it would be quite a bit more complicated. In general, a row-level trigger on
DUELcannot query theDUELtable– doing so would create a mutating table exception. You would need to create a collection in a package, a before statement trigger that initializes the collection, a row-level trigger that inserts the new pilot keys into the collection, and an after statement trigger that reads the data in the collection and does the validation. That’s quite a few moving pieces to manage in addition to the potential performance hit. If you’re really stuck with the trigger solution, however, there is an example of using the three trigger solution to work around mutating table exceptions on Tim Hall’s site.