Infolinks

Wednesday 20 February 2013

PL/SQL CODING



SOLUTION MANUAL(Odd#)


CHAPTER 1



CODING EXERCISES


1.        
SET SERVEROUTPUT ON
-- 6/3/2003
BEGIN
                DBMS_OUTPUT.PUT_LINE('Name:John Smith');
                DBMS_OUTPUT.PUT_LINE('Class:CMID563');
                DBMS_OUTPUT.PUT_LINE('Semester:Summer 2003');
                DBMS_OUTPUT.PUT_LINE('Session:1A2');
END;
/

3.
SET SERVEROUTPUT ON
DECLARE
                var_dpt_name                                                     department.dpt_name%TYPE;
                var_dpt_mgrssn                                                   department.dpt_mgrssn%TYPE;
                var_dpt_mgr_start_date                    department.dpt_mgr_start_date%TYPE;
                var_col                                  VARCHAR2(20);
BEGIN
                SELECT dpt_name, dpt_mgrssn, dpt_mgr_start_date
                INTO var_dpt_name, var_dpt_mgrssn, var_dpt_mgr_start_date
                FROM department
                WHERE dpt_no = &dept_number;
                DBMS_OUTPUT.PUT_LINE('Department Name:' || var_dpt_name);
                DBMS_OUTPUT.PUT_LINE('SSN of Department''s Manager:' || var_dpt_mgrssn);
                DBMS_OUTPUT.PUT_LINE('Manager''s start date:' || var_dpt_mgr_start_date);
EXCEPTION
                WHEN NO_DATA_FOUND THEN
                                DBMS_OUTPUT.PUT_LINE('No data found!');
END;
/


5.
SET SERVEROUTPUT ON
DECLARE
                a                                              NUMBER(10,2); -- set the precision to 10 with 2 decimal
BEGIN
                a := &b + &c * &d**2 - &e / 4;
                DBMS_OUTPUT.PUT_LINE('a:' || a);
EXCEPTION
                WHEN OTHERS THEN
                                DBMS_OUTPUT.PUT_LINE('Error!');
END;
/



CHAPTER 2



CODING EXERCISES


1.       
SET SERVEROUTPUT ON
DECLARE
                v_date DATE := TO_DATE('&sv_user_date', 'DD-MM-YYYY');
                v_day VARCHAR2(15);
BEGIN
                v_day := RTRIM(TO_CHAR(v_date, 'DAY'));
                IF v_day IN ('SATURDAY', 'SUNDAY') THEN
                                DBMS_OUTPUT.PUT_LINE(v_date||' falls on weekend');
                END IF;
                - control resumes here
                DBMS_OUTPUT.PUT_LINE('Done…');
END;
/

3.
SET SERVEROUTPUT ON
DECLARE
                v_final_grade NUMBER := &sv_num;
                v_letter_grade CHAR(1);
BEGIN
                IF v_final_grade BETWEEN 90 AND 100 THEN
                                v_letter_grade := 'A';
                ELSIF v_final_grade BETWEEN 80 AND 89 THEN
                                v_letter_grade := 'B';
                ELSIF v_final_grade BETWEEN 70 AND 79 THEN
                                v_letter_grade := 'C';
                ELSIF v_final_grade BETWEEN 60 AND 69 THEN
                                v_letter_grade := 'D';
                ELSE
                                v_letter_grade := 'F';
                END IF;
                -- control resumes here
                DBMS_OUTPUT.PUT_LINE('Letter grade is: '||v_letter_grade);
END;
/
5.
SET SERVEROUTPUT ON
DECLARE
                v_year number(4) := &sv_year;
BEGIN
                IF MOD(v_year,100) = 0 THEN
                                IF MOD(v_year,400) = 0 THEN
                                                DBMS_OUTPUT.PUT_LINE(v_year ||' is a Century and leap year');
                                ELSE
                                                DBMS_OUTPUT.PUT_LINE(v_year ||' is a Century and not a leap year');
                                END IF;
                ELSIF MOD(v_year,4) = 0 THEN
                                DBMS_OUTPUT.PUT_LINE(v_year ||' is not a century but is a leap year');
                ELSE
                                DBMS_OUTPUT.PUT_LINE(v_year ||' is not a century and not a leap year');
                END IF;
                DBMS_OUTPUT.PUT_LINE('Done…');
END;
/


7.
SET SERVEROUTPUT ON
DECLARE
                CURSOR mycur IS
                                SELECT * FROM shipment;
                total_value NUMBER(8,2) := 0;
                myrow shipment%ROWTYPE;
BEGIN
                OPEN mycur;
                LOOP
                                FETCH mycur INTO myrow;
                                EXIT WHEN mycur%NOTFOUND;
                                DBMS_OUTPUT.PUT_LINE('Description: '|| myrow.description);
                                DBMS_OUTPUT.PUT_LINE('Price: '|| myrow.itemrate);
                                DBMS_OUTPUT.PUT_LINE('Quantity on hand: '|| myrow.qty_hand);
                                DBMS_OUTPUT.PUT_LINE('value: '|| myrow.qty_hand* myrow.itemrate);
                                total_value := total_value + myrow.qty_hand * myrow.itemrate;
                END LOOP;  
                CLOSE mycur;
                                DBMS_OUTPUT.PUT_LINE('Total Value: '|| total_value);
EXCEPTION
                WHEN NO_DATA_FOUND THEN
                DBMS_OUTPUT.PUT_LINE('There are no items in this table');
END;
/

9.
SET SERVEROUTPUT ON
DECLARE
                CURSOR cur_emp is
                                SELECT emp_last_name, emp_middle_name, emp_first_name, emp_salary
                                                FROM employee, department
                                                WHERE emp_dpt_number = dpt_no
                                                AND dpt_name = 'Production'
                                                ORDER BY emp_first_name;

                rec_emp cur_emp%rowtype;
BEGIN
                DBMS_OUTPUT.PUT_LINE('Department: Production');
                OPEN cur_emp;
                LOOP
                                FETCH cur_emp INTO rec_emp;
                                EXIT WHEN cur_emp%NOTFOUND;

                                DBMS_OUTPUT.PUT_LINE('Full Name:' || rec_emp.emp_first_name || ' '
                                                || rec_emp.emp_middle_name || ' '
                                                || rec_emp.emp_last_name);
                                DBMS_OUTPUT.PUT('Salary:' || rec_emp.emp_salary);

                                IF rec_emp.emp_salary <= 30000 THEN
                                                DBMS_OUTPUT.PUT_LINE(' (Class A)');
                                ELSIF rec_emp.emp_salary BETWEEN 30000 AND 60000 THEN
                                                DBMS_OUTPUT.PUT_LINE(' (Class B)');
                                ELSE
                                                DBMS_OUTPUT.PUT_LINE(' (Class C)');
                                END IF;
                END LOOP;
                CLOSE cur_emp;
END;
/

11.

SET SERVEROUTPUT ON
DECLARE
                exp_not_found    EXCEPTION;
                v_day                                    VARCHAR2(10);
                var_counter          INTEGER := 0;
                CURSOR cur_emp is
                                SELECT emp_last_name, emp_first_name, emp_middle_name, emp_date_of_birth
                                                FROM employee;

                rec_emp cur_emp%rowtype;

BEGIN
                OPEN cur_emp;
                LOOP
                                FETCH cur_emp INTO rec_emp;
                                EXIT WHEN cur_emp%NOTFOUND;

                                v_day := RTRIM(TO_CHAR(rec_emp.emp_date_of_birth, 'DAY'));
                               
                                IF v_day = 'TUESDAY' THEN
                                                DBMS_OUTPUT.PUT_LINE('Full Name:' || rec_emp.emp_first_name || ' '
                                                || rec_emp.emp_middle_name || ' '
                                                || rec_emp.emp_last_name);

                                                var_counter := var_counter + 1;
                                END IF;
                               
                                IF var_counter = 2 THEN
                                                EXIT;
                                END IF;
                END LOOP;
                CLOSE cur_emp;
               
                IF var_counter <> 2 THEN
                                RAISE exp_not_found;
                END IF;
EXCEPTION
                WHEN NO_DATA_FOUND THEN
                                DBMS_OUTPUT.PUT_LINE('Could not find 2 employees born on Tuesday!');
                WHEN exp_not_found THEN
                                DBMS_OUTPUT.PUT_LINE('Could not find 2 employees born on Tuesday!');                  
END;
/

13.
SET SERVEROUTPUT ON
DECLARE
                sum_work_hours_planned                                assignment.work_hours_planned%TYPE := 0.0;
                sum_work_hours                                                                 assignment.work_hours%TYPE := 0.0;

                CURSOR cur_dep is
                                SELECT dpt_no, dpt_name, emp_last_name, emp_first_name, emp_middle_name
                                FROM department DEP, employee EMP
                                WHERE DEP.dpt_mgrssn = EMP.emp_ssn
                                ORDER BY emp_first_name;

                rec_dep cur_dep%rowtype;

                CURSOR cur_pro(par_dept_number department.dpt_no%TYPE) is
                                SELECT pro_name
                                FROM project
                                WHERE pro_dept_number = par_dept_number;


BEGIN
                OPEN cur_dep;
                LOOP
                                FETCH cur_dep INTO rec_dep;
                                EXIT WHEN cur_dep%NOTFOUND;
                                DBMS_OUTPUT.PUT_LINE('Department: ' || rec_dep.dpt_name);
                                DBMS_OUTPUT.PUT_LINE('Department Manager:' || rec_dep.emp_first_name ||
                                                                                                ' ' || rec_dep.emp_middle_name || ' ' || rec_dep.emp_last_name);

                                FOR rec_pro IN cur_pro(rec_dep.dpt_no)
                                LOOP
                                                DBMS_OUTPUT.PUT_LINE('Project Name:' || rec_pro.pro_name);
                                END LOOP;
                                SELECT SUM(work_hours), SUM(work_hours_planned)
                                INTO sum_work_hours, sum_work_hours_planned
                                FROM assignment                                                             
                                WHERE work_pro_number in (
                                                SELECT pro_number
                                                FROM project
                                                WHERE pro_dept_number = rec_dep.dpt_no);
                               
                                DBMS_OUTPUT.PUT_LINE('Total work hours:' || sum_work_hours);
                                DBMS_OUTPUT.PUT_LINE('Total work hours planned:' || sum_work_hours_planned);
                                               
                                DBMS_OUTPUT.PUT_LINE('**************************************');
                END LOOP;
                CLOSE cur_dep;
END;
/

15.

SET SERVEROUTPUT ON
DECLARE
                par_room_id                        bed.room_id%TYPE := '&room_id';
                CURSOR cur_pat IS
                                SELECT pat_last_name, pat_middle_name, pat_first_name, pat_id
                                                FROM patient PAT, bed BED
                                                WHERE PAT.bed_number = BED.bed_number
                                                AND room_id = par_room_id
                                                ORDER BY pat_first_name;

                rec_pat cur_pat%rowtype;
               
                CURSOR cur_staff(param1 patient.pat_id%type) is
                                SELECT DISTINCT staff_first_name, staff_middle_name, staff_last_name
                                                FROM staff STF, treatment TRM
                                                WHERE STF.staff_id = TRM.staff_id
                                                AND pat_id = param1;

                rec_staff cur_staff%rowtype;

BEGIN
                DBMS_OUTPUT.PUT_LINE('Room id:' || par_room_id);
                OPEN cur_pat;
                LOOP
                                FETCH cur_pat INTO rec_pat;
                                EXIT WHEN cur_pat%NOTFOUND;

                                DBMS_OUTPUT.PUT_LINE('Full Name:' || rec_pat.pat_first_name || ' '
                                                                                                                || rec_pat.pat_middle_name || ' '
                                                                                                                || rec_pat.pat_last_name);
                                DBMS_OUTPUT.PUT_LINE('Treated by:');
                                OPEN cur_staff(rec_pat.pat_id);
                                LOOP
                                                FETCH cur_staff INTO rec_staff;
                                                EXIT WHEN cur_staff%NOTFOUND;
               
                                                DBMS_OUTPUT.PUT_LINE('Staff member''s Name:' || rec_staff.staff_first_name || ' '
                                                                                                                                || rec_staff.staff_middle_name || ' '
                                                                                                                                || rec_staff.staff_last_name);
                                END LOOP;
                                DBMS_OUTPUT.PUT_LINE('**************************************');                                                            
                                CLOSE cur_staff;
                END LOOP;
                CLOSE cur_pat;
END;
/





17.

SET SERVEROUTPUT ON SIZE 10000;
DECLARE
                exc_exist EXCEPTION;
                var_cnt NUMBER;
                var_bol_exist BOOLEAN := FALSE; -- indicate if the situation where a patient is treated and prescribed
                                                                                                                                                -- by the same staff member exists.
                CURSOR cur_pre IS
                                SELECT DISTINCT PRE.pat_id, PRE.staff_id, hospital_title,
                                                staff_first_name, staff_middle_name, staff_last_name,
                                                pat_first_name, pat_middle_name, pat_last_name                  
                                FROM prescription PRE, staff STF, patient PAT
                                WHERE PRE.staff_id = STF.staff_id
                                AND PAT.pat_id = PRE.pat_id;
                                               
                rec_pre cur_pre%ROWTYPE;

BEGIN  
                OPEN cur_pre;
                LOOP
                                FETCH cur_pre INTO rec_pre;
                                EXIT WHEN cur_pre%NOTFOUND;

                                SELECT count(*) INTO var_cnt
                                                FROM treatment
                                                WHERE pat_id = rec_pre.pat_id
                                                AND staff_id = rec_pre.staff_id;

                                IF var_cnt > 0 THEN
                                                var_bol_exist := TRUE;
                                                DBMS_OUTPUT.PUT_LINE('Staff member''s Name:' || rec_pre.staff_first_name ||
                                                                ' ' || rec_pre.staff_middle_name || ' ' || rec_pre.staff_last_name);
                                                DBMS_OUTPUT.PUT_LINE('Patient''s Name:' || rec_pre.pat_first_name ||
                                                                ' ' || rec_pre.pat_middle_name || ' ' || rec_pre.pat_last_name);
                                                DBMS_OUTPUT.PUT_LINE('**************************************');
                                END IF;
                END LOOP;
                CLOSE cur_pre;

                IF var_bol_exist THEN
                                RAISE exc_exist;
                END IF;
EXCEPTION
                WHEN exc_exist THEN
                                DBMS_OUTPUT.PUT_LINE('Patient treated and prescribed by same staff found!');
END;
/






19.

SET SERVEROUTPUT ON
DECLARE
                var_cnt                  INTEGER             := 0; -- indicate the number of prescriptions for a specific patient.
                CURSOR cur_pat IS
                                SELECT PRE.pat_id, pat_last_name, pat_middle_name, pat_first_name
                                                FROM prescription PRE, patient PAT
                                                WHERE PRE.pat_id = PAT.pat_id
                                                GROUP BY PRE.pat_id, pat_last_name, pat_middle_name, pat_first_name
                                                HAVING count(*) > 1;
                                               
                rec_pat cur_pat%ROWTYPE;

                CURSOR cur_last_update(param1 prescription.pat_id%TYPE) IS
                                SELECT (SYSDATE - date_last_updated) date_diff
                                FROM prescription
                                WHERE pat_id = param1;
                                               
                rec_last_update cur_last_update%ROWTYPE;
                               
BEGIN  
                OPEN cur_pat;
                LOOP
                                FETCH cur_pat INTO rec_pat;
                                EXIT WHEN cur_pat%NOTFOUND;

                                OPEN cur_last_update(rec_pat.pat_id);
                                LOOP
                                                FETCH cur_last_update INTO rec_last_update;
                                                EXIT WHEN cur_last_update%NOTFOUND;

                                                IF rec_last_update.date_diff < 7 AND rec_last_update.date_diff > 0 THEN
                                                                var_cnt := var_cnt + 1;
                                                END IF;

                                                IF var_cnt = 2 THEN
                                                                DBMS_OUTPUT.PUT_LINE('Patient''s Name:' || rec_pat.pat_first_name ||
                                                                                ' ' || rec_pat.pat_middle_name || ' ' || rec_pat.pat_last_name);
                                                                EXIT;                                                    
                                                END IF;                
                                END LOOP;
                                CLOSE cur_last_update;
                               
                                var_cnt := 0; -- reset to 0 and start checking on another pat_id.
                END LOOP;
                CLOSE cur_pat;
END;
/

 


CHAPTER 3



CODING EXERCISES


1.        
SET SERVEROUTPUT ON
CREATE OR REPLACE FUNCTION incr_salary(
                ssn varchar2,percentage NUMBER)
RETURN NUMBER
IS
                rsal NUMBER(10,2);
BEGIN
                UPDATE employee
                SET emp_salary = ((emp_salary * percentage)/100+emp_salary)
                WHERE emp_ssn=ssn;
               
                SELECT emp_salary INTO rsal
                FROM employee
                WHERE emp_ssn = ssn;
               
                RETURN (rsal);
EXCEPTION
                WHEN NO_DATA_FOUND THEN   
                                DBMS_OUTPUT.PUT_LINE('Employee not found ');
END incr_salary;

3.
SET SERVEROUTPUT ON
CREATE OR REPLACE PROCEDURE emp_dept(
                empno IN VARCHAR2,
                deptname OUT VARCHAR2)
IS
BEGIN
                SELECT dpt_name
                INTO deptname FROM department
                WHERE dpt_no =
                                (SELECT emp_dpt_number FROM employee WHERE emp_ssn = empno) ;
EXCEPTION
                WHEN NO_DATA_FOUND THEN   
                                DBMS_OUTPUT.PUT_LINE('Employee or Dept does not exist ');
END emp_dept;

5.
CREATE OR REPLACE TRIGGER MYTRIG4                           
BEFORE UPDATE ON EMPLOYEE FOR EACH ROW
BEGIN                                                          
                IF (:NEW.EMP_SALARY < 20000) THEN                               
                                RAISE_APPLICATION_ERROR(21001,'SALARY IS TOO LESS');    
                END IF;                                                        
END;
/



7.
CREATE OR REPLACE PACKAGE pac_emp
AS
PROCEDURE pro_find_emp(
     par_emp_ssn IN employee.emp_ssn%TYPE,
     par_full_name OUT VARCHAR2,
     par_dept_no OUT department.dpt_no%TYPE);
FUNCTION fun_get_salary(
     par_emp_ssn employee.emp_ssn%TYPE,
     par_percentage               NUMBER)
     RETURN NUMBER;
END pac_emp;
/

CREATE OR REPLACE PACKAGE BODY pac_emp
AS
PROCEDURE pro_find_emp(
     par_emp_ssn IN employee.emp_ssn%TYPE,
     par_full_name OUT VARCHAR2,
     par_dept_no OUT department.dpt_no%TYPE)
                IS
                var_emp_last_name employee.emp_last_name%TYPE;
                var_emp_middle_name employee.emp_middle_name%TYPE;
                var_emp_first_name employee.emp_first_name%TYPE;
BEGIN
                SELECT emp_last_name, emp_middle_name, emp_first_name, emp_dpt_number
                                INTO var_emp_last_name, var_emp_middle_name, var_emp_first_name, par_dept_no
                                FROM employee
                                WHERE emp_ssn = par_emp_ssn;
                                               
                par_full_name := var_emp_first_name || ' ' || var_emp_middle_name || ' ' || var_emp_last_name;
EXCEPTION
   WHEN NO_DATA_FOUND then
      par_full_name := null;
      par_dept_no := -1;     
END pro_find_emp;

FUNCTION fun_get_salary(
     par_emp_ssn employee.emp_ssn%TYPE,
     par_percentage               NUMBER)
     RETURN NUMBER
IS
                ret_salary                              NUMBER(7,2);
BEGIN
                SELECT emp_salary
                INTO ret_salary
                FROM employee
                WHERE emp_ssn = par_emp_ssn;
               
                ret_salary := ret_salary * (1 + par_percentage / 100);
               
                return (ret_salary);
EXCEPTION
                WHEN NO_DATA_FOUND THEN
                                return (-1);
END fun_get_salary;
END pac_emp;
/

SET SERVEROUTPUT ON
DECLARE
     var_full_name      employee.emp_first_name%type;
     var_dpt_no                                      department.dpt_no%type;
BEGIN
      pac_emp.pro_find_emp('999666666',var_full_name, var_dpt_no);
      DBMS_OUTPUT.PUT_LINE(var_full_name || ' works in department ' || var_dpt_no);
      DBMS_OUTPUT.PUT_LINE('His adjusted salary is ' || fun_get_salary('999666666', 10));
END;
/


9.
CREATE OR REPLACE FUNCTION fun_class(
     par_ssn CHAR)
RETURN VARCHAR
IS
                ret_class                                VARCHAR2(10);
                var_salary                             NUMBER(7,2);
BEGIN
                SELECT emp_salary
                INTO var_salary
                FROM employee
                WHERE emp_ssn = par_ssn;

                IF var_salary <= 30000 THEN
                                ret_class :='Class A';
                ELSIF var_salary BETWEEN 30000 AND 60000 THEN
                                ret_class :='Class B';
                ELSE
                                ret_class :='Class C';
                END IF;
               
                RETURN (ret_class);
EXCEPTION
   WHEN NO_DATA_FOUND then
      RETURN ('No Class');
END fun_class;
/


11.

CREATE OR REPLACE TRIGGER tri_start_date
BEFORE INSERT OR UPDATE ON department FOR EACH ROW
BEGIN
                IF (RTRIM(TO_CHAR(:NEW.dpt_mgr_start_date, 'DAY')) IN ('SATURDAY', 'SUNDAY')) THEN
                                RAISE_APPLICATION_ERROR(-20000, 'The start date cannot be on a Saturday or Sunday');
                END IF;
END;
/

13.
DROP TABLE lt_asgn_history;
DROP TABLE asgn_history;

CREATE TABLE lt_asgn_history (
    work_emp_ssn              CHAR(9),
    work_pro_number           NUMBER(2),
    work_hours_completed      NUMBER(5,1),
    date_last_updated                            DATE, 
CONSTRAINT pk_lt_asgn_history
    PRIMARY KEY ( work_emp_ssn, work_pro_number, date_last_updated),
CONSTRAINT fk_lt_asgn_history
    FOREIGN KEY (work_emp_ssn, work_pro_number) REFERENCES assignment
) ;

CREATE TABLE asgn_history (
    work_emp_ssn              CHAR(9),
    work_pro_number           NUMBER(2),
    work_hours_completed      NUMBER(5,1),
    date_last_updated                            DATE, 
CONSTRAINT pk_asgn_history
    PRIMARY KEY ( work_emp_ssn, work_pro_number, date_last_updated),
CONSTRAINT fk_asgn_history
    FOREIGN KEY (work_emp_ssn, work_pro_number) REFERENCES assignment
) ;
               
CREATE OR REPLACE TRIGGER tri_assg
AFTER INSERT OR UPDATE OF work_hours_planned ON assignment
FOR EACH ROW
BEGIN  
                IF :new.work_hours_planned = 0 THEN
                                IF :new.work_hours >= 100 THEN
                                                INSERT INTO LT_ASGN_HISTORY (
                                                                work_emp_ssn, work_pro_number, work_hours_completed, date_last_updated)
                                                                VALUES (:new.work_emp_ssn, :new.work_pro_number,:new.work_hours, SYSDATE);
                                ELSE
                                                INSERT INTO ASGN_HISTORY (
                                                                work_emp_ssn, work_pro_number, work_hours_completed, date_last_updated)
                                                                VALUES (:new.work_emp_ssn, :new.work_pro_number,:new.work_hours, SYSDATE);
                                END IF;                
                END IF;
END;
/

UPDATE assignment
SET work_hours = 107.1, work_hours_planned = 0
WHERE work_emp_ssn = '999333333' AND work_pro_number = 3;
UPDATE assignment
SET work_hours = 34, work_hours_planned = 0
WHERE work_emp_ssn = '999222222' AND work_pro_number = 10;


No comments:

Post a Comment