=====
CS 328 - Week 6 Lecture 1 - 2025-02-24
=====

=====
TODAY WE WILL:
=====
*   announcements
*   DATA TIER - continuing intro to PL/SQL
*   intro to PL/SQL triggers
*   prep for next class

=====
*   should be working on Homework 5
    *   at-least-first-attempts due by 11:59 pm on Friday, February 28

*   should be finishing the activities in zyBooks chapters 1-2 

=====
UPCOMING SCHEDULE
=====
*   today: intro to PL/SQL triggers 

*   Wednesday, February 26 - review for Exam 1 (clicker questions included!)

*   Thursday, February 27/Friday, February 28
    *   CS Candidate TEACHING TALK at start of Thursday's lab -
        *** BSS 204 ***
        *   2 clicker-questions-worth of bonus clicker points
            if attend AND sign sign-in sheet at BEGINNING of talk

        *   then move to BSS 313 for clicker questions followed by
	    short-ish lab exercise on PL/SQL triggers for remainder of
	    Thursday's lab, due 11:59 pm on Thursday

    *   (Friday's lab - normal time and place, lab exercise due at end of lab)

*   11:59 pm Friday, February 28 
    *   at-least-first-attempts at Homework 5 problems due

    *   deadline for credit for zyBooks Chapters 1, 2 activities

*   Monday, March 3 - start discussing CSS (not on Exam 1)

*   11:59 pm Monday, March 3
    *   any final improved versions of problems from 
        Homeworks 1-5 are DUE, so that...

*   12:01 am Tuesday, March 4 
    *   selected EXAMPLE SOLUTIONS for Homeworks 1-5 
        can be made reachable on Canvas, for Exam 1 study use

*   Wednesday, March 5 - Exam 1

*   Thursday, March 6/Friday, March 7
    *   (Thursday's lab - normal time and place, lab exercise due at end of lab)

    *   CS Candidate TEACHING TALK at start of Friday's lab
        *** BSS 204 ***
        *   2 clicker-questions-worth of bonus clicker points
            if attend AND sign sign-in sheet at BEGINNING of talk

        *   then move to BSS 313 for clicker questions followed by
	    short-ish lab exercise writing an external CSS style sheet
	    for remainder of Friday's lab, due 11:59 pm on Friday

*   (Homework 6 comes out the weekend of March 8-9)

*   Monday, March 10 
    *   CS Candidate TEACHING TALK at start of lecture - SH 108
    
    *   2 clicker-questions-worth of bonus clicker points
        if attend AND sign sign-in sheet at BEGINNING of talk

    *   then regular lecture on more CSS
        (which will be supplemented by a recorded, posted lecture)

*   Wednesday, March 12 - more discuss of CSS

*   (WILL be labs on Thursday, March 13/Friday, March 14!)

*   (Homework 6's at-least-first-attempts will be due 11:59 pm
    Friday, March 14)

*   (Homework 7 comes out the weekend of March 15/16,
    but will have at-least-first-attempts due
    by 11:59 pm Friday, March ***28***
    because of Spring Break March 17-21)

PLEASE contact me if you have any questions about the above!
===== 

=====
PL/SQL triggers
=====
*   trigger: a subroutine you don't directly call --
    instead, it gets executed, or "fired", or "triggered",
    when the appropriate action happens on the database

    *   here, an appropriate action is a specified action
        on a specified database table

*   why?
    *   can be useful for enforcing more-sophisticated data
        integrity requirements;

    *   can allow enforcement of more-customized domain integrity
        requirements

        *   for example, they can do more than a create table's
	    check clause can
	    
    *   can check that certain requirements are met before
        an action is allowed to proceed

    *   can make sure certain updates are made to other
        tables after an action has been done

        *   (so, might help protect your data 
            when multiple potential applications written
	    by potentially many programmers will be using it)

*   a trigger CAN check for stuff BEFORE a desired action,
    and PREVENT it if it deems it unaccaptable;

    a trigger CAN perform additional needed/desired actions
    AFTER an action, to make sure they get done

=====
BASIC PL/SQL trigger syntax:
=====
*   basic trigger header syntax (there ARE more optional clauses!):

    { } - choose ONE of the choices within (separated by |)
    [ ] - these are optional

    CREATE OR REPLACE TRIGGER desired_trigger_name
        {BEFORE | AFTER}
	{DELETE | INSERT | UPDATE}
	ON desired_table_name
	[FOR EACH ROW]
    [DECLARE
        local_declarations_here]
    BEGIN
        statements;
    [EXCEPTION
        WHEN ...]
    END;
    /
    show errors

*   FOR EACH ROW - means to fire the trigger
    once for each individual row affected by the specified
    triggering action

*   the Oracle DBMS seems to be very concerned about
    preventing "circular" trigger firings --

    for example, you are not allowed to perform a
    SELECT on the table the trigger is for...!

    you'll get THIS error message:

    ORA-04091: table ST10.EMPL is mutating, trigger/function may not see it

    *   HOWEVER, frequently, this is OK, because
        there IS a way to grab some useful info about
	the triggering action;

=====
*   sometimes a trigger needs more info about the action
    that triggered it;

    there is syntax for grabbing attribute values from
    the action

    *   NOTE: trigger NEEEEEEDS to include FOR EACH ROW for this syntax to work!

    *   for a trigger on an insert:

        :new.desired_attrib_name

        ...is the value of that attribute in the row being inserted

    *   for a trigger on a delete:

        :old.desired_attrib_name

        ...is the value of that attribute in the row being deleted

    *   for a trigger on an update:

        :old.desired_attrib_name

        ...is the value of that attribute in the row BEFORE it is updated

        :new.desired_attrib_name

        ...is the value of that attribute in the row AFTER it is updated

*   these take most (but not all!) of the sting out of the fact
    that a trigger CAN. NOT. QUERY itself...
    *   that is, a trigger can contain a select on a table
        that is NOT the table it is triggered on

        (but NOT on the table the trigger is triggered on)

=====
raise_application_error
=====
*   how can a BEFORE trigger prevent thre triggering action?

    it can call the procedure:

    raise_application_error(desired_err_num, desired_err_msg);

    *   desired_err_num - a negative integer in the range -20000 .. -20999

        desired_err_msg - a character string up to 2048 bytes long

=====
*   in current Oracle versions, you CAN have multiple triggers on the
    SAME table

    *   BUT -- you need to be careful, because if you have such multiple
        triggers on the same action(s) for the same table,

        the ORDER of the FIRING/execution might be difficult to determine
	UNLESS you include a FOLLOWs clause
	
*   you CAN also write ONE trigger that handles more than one possible
    action -- for example, this trigger would fire on either
    an update OR a delete OR an insert on desired_table:

    create or replace trigger my_new_trigger
        BEFORE UPDATE OR DELETE OR INSERT   
        on desired_table
        ...

    *   inside this trigger,
        you can use a boolean expression

	INSERTING - will be true if this was triggered on an insert
        UPDATING - will be true if this was triggered on an update
	DELETING - will be true if this was triggered on a delete

        if INSERTING then
            ...
        elsif DELETING then
            ...
        elsif UPDATING then
            ...
	else
	    ...
        end if;

*   (and you can limit a trigger to only fire on an action on a
    particular column,

    or for each row meeting some specified boolean condition;

    create or replace trigger desired_trig
        {before | after}
        {delete | insert | update [OF column_name1 [, column_name2 ...]]
            [or {delete | insert | update [OF column_name1 [, column_name2 ...]]}}
        on desired_table
        [for each row
            [WHEN (bool_expr)]]

    ...see the posted triggers reference on the course PL/SQL references
    page if you are interested)