Required: Cover Page (Release Form) The SQL Midterm Exam The Final Project
Required: Cover Page (Release Form) The SQL Midterm Exam The Final Project
Required: Cover Page (Release Form) The SQL Midterm Exam The Final Project
Project
Class:
Professor:
Term / Year:
Effort [minutes]
Student Name (s)
Assignment:
Date of Submission:
Part 1 Test:
SELECT * FROM qdel;
Part 2:
alter table QSale
add
(SaleDate date);
DECLARE count1 number(10);
date2 date;
BEGIN
count1:= 1;
While count1 <27
Loop
date2 := to_Date('01, 01, 2011', 'MM, dd, YYYY');
update QSALE
set SaleDate = date2 + round(dbms_random.value() * 364 )
Where count1 +1000= saleno;
count1 := count1+1;
END LOOP;
END;
Part 2 Test:
SELECT * FROM QSALE;
Step 2: Add QtyOnHand field for the level of inventory in QITEM table and set up initial values
to 100.
alter table
QITEM
add
(
QtyOnHand number(6) Default 100); -- greater than 0
Test:
SELECT * FROM QITEM;
Part 1 Test:
SELECT * FROM QDELADMIN;
Part 2:
CREATE or replace VIEW QDELsale AS
SELECT SUm(DELQTY) as DELQTY, QDEL.ITEMNAME as ItemName FROM QDEL WHERE
(QDEL.DEPTNAME != 'management'
AND QDEL.DEPTNAME != 'accounting' AND QDEL.DEPTNAME != 'personnel' AND
QDEL.DEPTNAME != 'purchasing'
AND QDEL.DEPTNAME != 'marketing')GROUP BY ITEMNAME;
Part 2 Test:
SELECT * FROM QDELsale;
Part 3:
UPDATE QITEM
SET QITEM.QTYONHAND = QITEM.QTYONHAND + (SELECT QDELSale.DELQTY FROM QDELSale
WHERE QITEM.ITEMNAME = QDELSale.ITEMNAME )
WHERE EXISTS (SELECT QDELSale.ITEMNAME FROM QDELSale WHERE QITEM.ItemName =
QDELSale.ItemName);
Part 3 Test:
SELECT * FROM QITEM;
Part 4:
UPDATE QITEM
SET QITEM.QTYONHAND = QITEM.QTYONHAND - (SELECT QDELADMIN.DELQTY FROM QDELADMIN
WHERE QITEM.ITEMNAME = QDELADMIN.ITEMNAME )
WHERE EXISTS (SELECT QDELADMIN.ITEMNAME FROM QDELADMIN WHERE QITEM.ItemName =
QDELADMIN.ItemName);
Part 4 Test:
SELECT * FROM QITEM;
b)
UPDATE QITEM
SET QITEM.QTYONHAND = QITEM.QTYONHAND - (SELECT SUM(QSALE.SALEQTY) FROM QSALE
WHERE QITEM.ITEMNAME = QSALE.ITEMNAME )
WHERE EXISTS (SELECT QSale.ITEMNAME FROM QSALE WHERE QITEM.ItemName =
QSALE.ItemName);
Test:
SELECT * FROM QITEM;
c)
Provide Inventory status report indicating QtyOnHand and for all values under a 100
initiate one delivery in 2012 of random values (say between 100 and 200) to sales departments
only! Take care if necessary of items that had no sales or attempting to sell more than available
quantity.
Create or replace Trigger updateQtyOnHand
AFTER UPDATE on QITEM
DECLARE counter number(3);
rowz number(3);
onhand number(6);
rando number(6);
name2 varchar(30);
dept2 varchar(10);
spl2 number(3);
BEGIN
rowz := 51;
SELECT max(QDEL.Delno) INTO counter From Qdel;
while rowz < counter Loop
SELECT ItemName Into name2 From Qdel where delno = rowz;
d)
SELECT * FROM
update QITEM
SET qtyonHand = 90
--222
WHERE ITEMNAME = 'pocket knife-nile';
SELECT * FROM
Step 4: Reconstruct QEMP table so that BOSS information from employees table will became
MANAGER information in new QORG table derived from QDEPT. Start QORG by inserting
SUNRISE (company) as organizational unit managed by the top BOSS (and use a query on
QEMP to determine the top BOSS). As a result QEMP will also need to change, not to have BOSS
information, and QDEPT is to be deleted once all information migrates to QORG.
create table QORG as select QDEPT.*, q2.x as managINFO
FROM Qdept join (SELECT deptname,min(qemp.empno) as x
from qemp
group by qemp.deptname) q2
on q2.deptname= qdept.deptname;
-- top boss is alice!!!
Test:
select * from QORG
order by managinfo asc, deptname asc;
Step 5: Hire five salespersons as employees working in department involved with sales in 2012
(insert five records).
insert into QEMP(EMPNO, EMPFNAME, EMPSALARY, Deptname)
Values((SELECT max(empno) from qemp)+1, 'John', 99999, 'books');
insert into QEMP(EMPNO, EMPFNAME, EMPSALARY, Deptname)
Values((SELECT max(empno) from qemp)+1,'Matt', 14500, 'furniture');
insert into QEMP(EMPNO, EMPFNAME, EMPSALARY, Deptname)
Values((SELECT max(empno) from qemp)+1, 'david', 1100, 'equipment');
insert into QEMP(EMPNO, EMPFNAME, EMPSALARY, Deptname)
Values((SELECT max(empno) from qemp)+1, 'Zombie', 16000, 'clothes);
insert into QEMP(EMPNO, EMPFNAME, EMPSALARY, Deptname)
Values((SELECT max(empno) from qemp)+1, 'Claire', 15000, 'recreation');
Test:
Step 6: Create QCUSTOMER table with 20 prospects and generate one sale to each in 2013, keeping
inventory information updated (automatically). Note need to expand QSALE to include FK to customer
(an optional field as they still be some sales to unidentified customers and for backward compatibility).
create table qcustomer (custid number(8), name varchar(20),
address varchar(20),
constraint qcustomer_pk PRIMARY KEY (custid));
alter table qsale add( custid number(8), constraint fk_qcustomer
FOREIGN Key (custid) references qcustomer(custid));
insert
insert
insert
insert
insert
insert
insert
insert
into
into
into
into
into
into
into
into
qcustomer
qcustomer
qcustomer
qcustomer
qcustomer
qcustomer
qcustomer
qcustomer
values
values
values
values
values
values
values
values
insert
insert
insert
insert
insert
insert
insert
insert
insert
insert
insert
insert
into
into
into
into
into
into
into
into
into
into
into
into
qcustomer
qcustomer
qcustomer
qcustomer
qcustomer
qcustomer
qcustomer
qcustomer
qcustomer
qcustomer
qcustomer
qcustomer
values
values
values
values
values
values
values
values
values
values
values
values
Test:
select * from qcustomer;
Step 7: In January 2014 SUNRISE started accepting ORDERS for multiple ITEMS (one per
ORDERLINE) and started fulfilling sales by mail. To keep old system intact a new MSALE table is to be
created to handle possibly multiline order fulfillment. Show DDL code (for new tables ORDER,
ORDERLINE, and MSALE) and illustrate with a few transactions.
TABLES
create table sunriseorder (custid number(8),orderid number(8),orderdate date);
create table orderlines(orderId number(8),orderlineId number(8),itemname
varchar(30),qty number(5),price number(10));
create table MSALE (MSaleID number(8),orderID number(8), price number(8),payMethod
varchar(5),filled number(2));
POPULATE TABLE 1
insert into sunriseorder
values(3,4,SYSDATE);
insert into sunriseorder
values(4,5,SYSDATE);
insert into sunriseorder
values(4,6,SYSDATE);
SELECT * FROM sunriseorder where orderid>3;
TRIGGER 1
create or replace trigger checkOrder
after insert on orderlines
--for each row
DECLARE OI number(8);
price1 number(8);
quant number(8);
oi2 number(8):=0;
oi3 number(8):=0;
oiline number(8);
BEGIN
--SELECT orderlineId into oiline from orderlines where
orderlineId=:new.orderLineId;
SELECT orderId into OI from orderlines where orderlineId=(SELECT max(OrderlineID)
from orderlines);
SELECT orderId into OI2 from sunriseOrder where orderId=OI;
--delete from orderlines where orderlineId=(SELECT max(OrderlineID) from
orderlines);
SELECT count(orderId) into OI3 from mSALE where orderId=OI;
if (oi2>0)
then
if (oi3=1)
then
DBMS_OUTPUT.PUT_LINE('the row already has a SALE, this row is uneditable');
delete from orderlines where orderlineId=(SELECT max(OrderlineID) from
orderlines);------wrong, delete or
else
DBMS_OUTPUT.PUT_LINE('the row works, when done make an msale');
end if;
else
DBMS_OUTPUT.PUT_LINE('there must be a sunriseOrder first');
--delete from orderlines where orderlineId=(SELECT max(OrderlineID) from
orderlines);------wrong, delete linorder
end if;
exception when others then
dbms_output.put_line('hhello');
delete from orderlines where orderlineId=(SELECT max(OrderlineID) from
orderlines);
END;
/*NOTES
This trigger checks to see if there is an sunriseorder corresponding to the order_id.
If there is not, it deletes the row put into orderlines.
This trigger checks to see if there is a MSALE corresponding to the order_id,
If there is not it allows for the creation of the row.
Otherwise it deletes the orderliness row.
*/
POPULATE TABLE 2
insert into orderlines
values(4,(SELECT max(orderlineID) from orderlines)+1,'sextant',1,10);
insert into orderlines
values(4,(SELECT max(orderlineID) from orderlines)+1,'compass',1,11);
insert into orderlines
values(5,(SELECT max(orderlineID) from orderlines)+1,'sextant',1,10);
insert into orderlines
values(5,(SELECT max(orderlineID) from orderlines)+1,'sextant',2,10);
insert into orderlines
values(6,(SELECT max(orderlineID) from orderlines)+1,'sextant',1,10);
SELECT * FROM orderlines where ordered>3;
TRIGGER 2
create or replace trigger MakeSale
after insert on MSALE
declare
oi number (8);
oi2 number(8);
q number(8);
countz number(8);
x number (8);
y number (8);-- the number of lines between orderlines
name2 varchar(20);
fill number(2);
msaleCount number(2);
payment varchar(3);
hand number(6);
hand2 number(6);
z number(8);
begin
SELECT orderid into oi from msale where msaleid=(SELECT max(msaleid) from msale);
Select orderid into oi2 from sunriseorder where orderid= oi;
SELECT sum(price*qty) into q from orderLines where orderid= oi;
update msale
set PRICE= q
where msaleid=(SELECT max(msaleid) from msale);
-------------- add later error now
SELECT count(orderid) into msaleCount from msale where orderid=oi;
if(msaleCount>1)
then
delete msale
where msaleid=(select max(msaleid) from msale where orderid=oi);
end if;
SELECT paymethod into payment from msale where orderid =oi;
SELECT filled into fill from msale where orderid=oi;
if(payment='CC' and fill=0)
then
fill:=1;
x:=0;
end if;
end loop;
end if;
end if;
exception
when others then
delete msale
where orderid= oi;
end;
POPULATE TABLE 3
Insert into msale
Values(1,5,0,'CC',0);
SELECT * FROM orderlines where orderid=5;
/*
SO as you can see, the trigger checkorder stops a row from being inserted into
lineorders incorrectly.
The trigger make sale finalizes the sale, charging the client money. It adds up
the total cost of the items.
It creates a msale line that stops lineorders from being changed. It also makes
sure every msale has a unique orderid.
Step 8: SUNRISE also started in January 2014 to accept payments by CC for all mail orders if inventory
is available.
The trigger makesale(seen in problem 7), triggers a previously made trigger when it
inserts into qsale
With the new information. This then updates qitems qtyonhand. But this is only
done when the payment method for a msale is CC.
Here is the code in the trigger that actually does this, for the full trigger please see
previous problem.
Step 9: SUNRISE is adding its own automatic orders SORDERS to suppliers to initiate delivery of all
ITEMS when their quantity at hand reaches a certain minimal level (for10% of the average for the past
year, note that a running average needs to be calculated during the current year and kept for the past year).
So a trigger needs to be made that will use a function for calculating running avg. How would you
prepare, in 2015, for this new functionality in order to be ready for 2016.
Part 1:
create table sorders (itemname varchar(50),qty number,cutoff number);
create table ex6 (itemname varchar(50), qty number, counts number, average number,
yearaverage number );
insert into ex6(itemname) select itemname from qitem;
update ex6 set counts=1,qty=100,average=0, yearaverage
=round(dbms_random.value(1,100));
update ex6 set (itemname, qty)= (select qitem.itemname, qitem.qtyonhand from qitem
where qitem.itemname=ex6.itemname);
--Item name is the same as qitems name. QTY and COUNT is for getting the running
average Each time an items qtyonhand on QITEM table its gets added to the qty
column and divided by count that gets this years running average (under the
AVERAGE COLUMN.) The YEARAVERAGE column is last years average.
Part 2:
--TRIGGER COMMENT---Whenever a qitem qtyonhand this trigger gets the running average of the item in
the EX6 table and if the qty is below 10% of last years average (YEARAVERAGE)
then it will be added into our SORDERS table.
CREATE OR REPLACE TRIGGER ggg
after update ON qitem
for each row
DECLARE
itemname varchar(20);
newname varchar(20);
newnum number;
qty number;
avgs number;
yavg number;
countss number;
BEGIN
if :new.qtyonhand != :old.qtyonhand then
Part 3:
--THIS will set our qty to BELOW our 10% average It will get added into our
SORDERS table. It will also get running average for hammock in EX6 table.
update qitem set qtyonhand=1 where itemname='hammock';
select * from qitem;
--THIS SHOWS THAT HAMMOCK IS ADDED TO OUR SORDERS TABLE BECAUSE THE QTYONHAND IS
BELOW 10% OF LAST YEARS AVERAGE. CUTOFF IS THE 10% OF LAST YEAR AVERAGE.
--REPEAT FROM ABOVE. The item elephant polo stick will be added to SORDERS
because qty=2 is below 10% of YEARAVERAGE (last years average).
update qitem set qtyonhand=15 where itemname='sextant';
update qitem set qtyonhand=35 where itemname='map case';
update qitem set qtyonhand=2 where itemname='elephant polo stick';
Step 10: SUNRISE is considering expanding the DB with INVOICES to old customers (if inventory on
hand cannot completely fulfill an order), but will still accept new customers for orders that can be
completely fulfilled from on hand inventory.
--EXAMPLE CUST TABLE
--THIS IS A CUSTOMER TABLE WITH OUR CUSTOMERS AND THEIR ORDERS
create table custex (custid number,name varchar(20),address varchar(50),orders
varchar(50));
--INSERTING OLD CUSTOMERS.
insert into custex values (1,'SAM','123 main street','hammock');
--CREATING OUR NEW TABLE THAT TELLS US WHO GETS AN INVOICE AND WHO DOESNT.
--IF A CUSTOMER ORDER QTY IS ZERO THEN HE OR SHE GETS AN INVOICE
create table invoice(custid number,name varchar(20),address varchar(50),orders
varchar(50),invoice varchar(5));
--MAKING ITEM NAMED HAMMOCK = 0. THIS SHOULD ALLOW SAM TO GET AN INVOICE.
update qitem set qtyonhand=0 where itemname='hammock';
--THIS LOOPS THROUGH OUR CUSTOMERS AND DETERMINES WHO GETS AN INVOICE.
select * from qitem;
select * from custex;
set serveroutput on
declare
v varchar(50);
v2 varchar(50);
v3 varchar(50);
v4 varchar(50);
nums number;
nums2 number;
counters number;
begin
counters:=1;
loop
select
select
select
select
BEGIN
select itemname into newname from qitem where itemname=:new.orders;
select itemname into newname from qitem where itemname=:new.orders;
select qtyonhand into newnum from qitem where itemname=newname;
if newnum=0 then
insert into invoice values(:new.custid,:new.name,:new.address,:new.orders,'NO');
--dbms_output.put_line(v);
else
insert into invoice values(:new.custid,:new.name,:new.address,:new.orders,'YES');
end if;
END;
--INSERTING NEW CUSTOMERS. NOW CUSTOMERS ITEMS THAT HAVE A QTY ABOVE ZERO WILL
GET AN INVOICE. WHEN QTY IS ZERO THEY WILL NOT. FOO WILL NOT GET AN INVOICE.
insert into custex values (5,'aka','8 8th street','compass');
insert into custex values (6,'foo','8 8th street','hammock');
insert into custex values (7,'dfsdf','8 8th street','sextant');
Step 11 (bonus 20 points max): To demonstrate final DB, create 3-4 intermediate level SQL queries, not
possible in the old QSALE DB, illustrating interests of various stakeholders (managers, customers,
suppliers, employees).
1:
create or replace view QuantityCheck as
select qi.itemname, qi.qtyonhand as quantity, qs.saleqty
from qitem qi join qsale qs on qi.itemname = qs.itemname
Test:
select * from quantitycheck;
2:
declare
custid number(8);
custname varchar(20);
custaddress varchar(20);
cursor custinfo is
Test:
3:
select max(qtyonhand) from qitem
where exists (select * from ex6 where itemname = 'camel saddle');
Test:
4: