Please send questions to st10@humboldt.edu .

-- last modified: 12-1-10

-- NOTE: you will NOT see the results of the dbms_output commands unless
--     you run the command:	set serveroutput on

-- this creates the trigger inventory_update, which updates the
-- quantity in the inventory table before an order is inserted into 
-- the orders table.
--
-- it complains and does not permit the orders insert if the
-- order is for more than the current quantity available.

-- instead of dropping beforehand, let's play with 'create or replace'
-- below...
-- drop trigger inventory_update;

-- EVERY TRIGGER needs to indicate BEFORE or AFTER WHAT actions
-- on WHAT table it needs to be executed....
--
-- 'for each row' means to perform trigger actions for EACH
-- individual row affected by that trigger action
--
-- think carefully: should action be done BEFORE or AFTER triggering
-- event?
--
-- note: Oracle appears to only permit one trigger per table;
-- thus, you CAN have more than one action after the 'before' or 'after';
--
-- also note: Oracle takes some pains to avoid undesirable trigger
-- cascades; beware;

create or replace trigger inventory_update
	before insert
	on orders
	for each row
declare
	-- declare section can be omitted if you do not want
	-- to declare any variables...

	amt_ordered	integer;
	item_ordered	integer;
	amt_in_stock	integer;
begin
	-- set some variables for convenience

	-- :new.colName lets you use the value of attribute colName
	-- of the newly[to be]
	-- inserted or updated row.
	--
	-- :old.colName lets you use the value of the attribute
	-- colName of the previous[to be]deleted or updated row  

	-- set variable amt_ordered to the value of
	-- attribute order_quantity in the NEWLY to-be-inserted
	-- orders row; note the := for assignment to a variable

	amt_ordered := :new.order_quantity;
                       
	-- set variable item_ordered to be the value of
	-- attribute item_num in the NEWLY to-be-inserted
	-- orders row

	item_ordered := :new.item_num;

	-- get quantity of that item in inventory
 	-- and put it into variable amt_in_stock
	-- (note use of PL/SQL 'into' clause in this
	-- otherwise-normal select statement)

	select	item_quantity
	into 	amt_in_stock 
	from	inventory
	where 	item_num = item_ordered;

	-- triggers seem to not like a select of the
	-- table the trigger is upon; try to avoid
	-- those...

	-- is it "safe" to do this insert?

	-- don't allow an order for a NEGATIVE or 0 number of items!

	if (amt_ordered <= 0) then
		raise_application_error ( -20600, 'Order number ' ||
            		:new.order_num || ' cannot be placed, '
			|| 'because order quantity ' || amt_ordered
			|| ' must be at least 1.');
	end if;
	
	-- don't allow an order for more of something than we have
	-- in inventory;

	if (amt_in_stock >= amt_ordered) then

		-- it is safe --- update this item's quantity
		-- in the inventory table

		update 	inventory
		set 	item_quantity = item_quantity - amt_ordered
		where	item_num = item_ordered;

		dbms_output.put_line('Successfully updated inventory'
				     || ' item number: ' || item_ordered);
	
	else
		-- this will PREVENT the insert into orders,
		-- and will complain with the following
		-- error message!!

		raise_application_error ( -20601, 'Order number ' ||
            		:new.order_num || ' cannot be placed, '
			|| 'because order quantity ' || amt_ordered
			|| ' of item ' || item_ordered || 
			' is more than stock on hand of ' ||
			amt_in_stock);
	end if;
end;
-- this slash below seems to be necessary to "compile" trigger!
-- DO NOT FORGET THIS!!!
/	

-- NOTE --- if you get the error message, upon creating a trigger, that:
--         Warning: Trigger created with compilation errors.
-- then the following will give you information about those errors:
-- (there aren't any right now)

show errors