PLSQL


My PLSQL PRACTICES

1. Evaluate your declarations. 

a. DECLARE v_name, v_dept VARCHAR2(14);
This declaration is illegal, because Oracle does not allow two variables to be declared together.

b. DECLARE v_test NUMBER(5);
Legal

c. DECLARE V_MAXSALARY NUMBER(7,2) = 5000;
This declaration is illegal, because assignment is done using := operator, whereas comparison is done using = operator.

d. DECLARE V_JOINDATE BOOLEAN := SYSDATE;
ILLEGAL… Can’t assign date value to Boolean variable. Oracle throws following error.
     PLS-00382: expression is of wrong type


2. Determine resulting datatype

a. v_email := v_firstname || to_char(v_empno);
 Ans: Result would be of varchar2

b. v_confirm := to_date('20-JAN-1999', 'DD-MON-YYYY');

OUTPUT WILL BE IN DATE.

Explanation:
create or replace procedure VALIDST

as
          v_confirm DATE;

begin

          v_confirm := to_date('20-Jan-1999','DD-MON-YYYY');

          dbms_output.put_line(v_confirm);

end;

/

EXECUTION
SQL> @c:\TRUPTI\PLSQL\VALIDSTATEMENT.TXT

Procedure created.

SQL> EXEC VALIDST

PL/SQL procedure successfully completed.

SQL> SET SERVEROUTPUT ON
SQL> EXEC VALIDST
20-JAN-99

c. v_sal := (1000*12) + 500

OUTPUT WILL BE IN NUMBER

 Explanation:
create or replace procedure VALIDST2
as
          v_sal NUMBER;
begin
          v_sal := (1000*12) + 500;
          dbms_output.put_line(v_sal);
end;

/
EXECUTION

SQL> @c:\TRUPTI\PLSQL\VALIDSTATEMENT2.TXT

Procedure created.

SQL> EXEC VALIDST2
12500

PL/SQL procedure successfully completed.

d. v_test := FALSE;

MY_REMAINDER: OUTPUT WILL BE IN BOOLEAN. BUT DBMS_OUTPUT.PUT_LINE DOESN’T ALLOW BOOLEAN VARIABLE TO BE DISPLAYED. HENCE, WE CAN USE BOOLEAN VALUE FOR COMPARISON.

Explanation:
create or replace procedure VALIDST3
as
          v_TEST BOOLEAN;

begin

          v_TEST := FALSE;
          if V_TEST = True then
                   dbms_output.put_line('True portion');
          else
                   dbms_output.put_line('False portion');
          end if;
end;

/


e. v_temp := v_temp1 < (v_temp2/ 3);

Output will be in boolean

Explanation:
create or replace procedure VALIDST4
as
          v_tmp boolean;
          v_tmp1 number(5) := 15;
          v_tmp2 number(5) := 10;
begin
          v_tmp := v_tmp1 < (v_tmp2 / 5);
          if v_tmp then
                   dbms_output.put_line('true');
          else
                   dbms_output.put_line('true');
          end if;
end;
/
EXECUTION
SQL> @c:\TRUPTI\PLSQL\VALIDSTATEMENT4.TXT
Procedure created.

SQL> EXEC VALIDST4
true
PL/SQL procedure successfully completed.


f. v_var := sysdate;

Output will be of DATE type.

Explanation:
create or replace procedure VALIDST5
as
          v_DT DATE;
begin

          v_DT := SYSDATE;
          dbms_output.put_line(v_DT);
end;

/

SQL> @c:\TRUPTI\PLSQL\VALIDSTATEMENT5.TXT
Procedure created.

SQL> EXEC VALIDST5
05-OCT-11
PL/SQL procedure successfully completed.


Part A

3. DECLARE
v_custid NUMBER(4) := 1600;
v_custname VARCHAR2(300) := 'Women Sports Club';
v_new_custid NUMBER(3) := 500;
BEGIN
DECLARE
v_custid NUMBER(4) := 0;
v_custname VARCHAR2(300) := 'Shape up Sports Club';
v_new_custid NUMBER(3) := 300;
v_new_custname VARCHAR2(300) := 'Jansports Club';
BEGIN
v_custid := v_new_custid;
v_custname := v_custname || ' ' || v_new_custname;
END;
v_custid := (v_custid *12) / 10;
END;
/

Evaluate the PL/SQL block above and determine the data type and value of each of the following variables
according to the rules of scoping:

a. The value of V_CUSTID at position 1 is:
b. The value of V_CUSTNAME at position 1 is:
c. The value of V_NEW_CUSTID at position 2 is:
d. The value of V_NEW_CUSTNAME at position 1 is:
e. The value of V_CUSTID at position 2 is:
f. The value of V_CUSTNAME at position 2 is:


DECLARE
         v_custid NUMBER(4) := 1600;
         v_custname VARCHAR2(300) := 'Women Sports Club';
         v_new_custid NUMBER(3) := 500;
        
        BEGIN
              DECLARE
                   v_custid NUMBER(4) := 0;
                   v_custname VARCHAR2(300) := 'Shape up Sports Club';
                   v_new_custid NUMBER(3) := 300;
                   v_new_custname VARCHAR2(300) := 'Jansports Club';
              
                     BEGIN
                   v_custid := v_new_custid;
                    v_custname := v_custname || ' ' || v_new_custname;
                  dbms_output.put_line(' Cust_id in inner block  :-  ' || v_custid);
                   dbms_output.put_line(' Cust_name in inner block   :-   ' || v_custname);
                   dbms_output.put_line(' Cust_new_id in inner block  :-  ' || v_new_custid);
              END;
         
              v_custid := (v_custid *12) / 10;
              dbms_output.put_line(' Cust_id in outer block  :-   ' ||v_custid);
              dbms_output.put_line(' Cust_name in outer block   :-  ' || v_custname);
              dbms_output.put_line(' Cust_new_id in outer block  :-  ' || v_new_custid);
 END;
/

Copy and paste it in sql. Ctrl+c and right click on sql. Or Edit -> paste.

OUTPUT

Cust_id in inner block  :-  300
Cust_name in inner block   :-   Shape up Sports Club Jansports Club
Cust_new_id in inner block  :-  300
Cust_id in outer block  :-   1920
Cust_name in outer block   :-  Women Sports Club
Cust_new_id in outer block  :-  500

PL/SQL procedure successfully completed.


Note: These exercises can be used for extra practice when discussing how to interact with the Oracle server and write control structures.

4. Write a PL/SQL block to accept a year and check whether it is a leap year. For example, if the year entered is 1990, the output should be “1990 is not a leap year.”
Hint: The year should be exactly divisible by 4 but not divisible by 100, or it should be divisible by 400


SQL> DECLARE
        YR NUMBER(6,2) := &YR;
        BEGIN
     IF (MOD(YR,4) = 0) AND (MOD(YR,100) <> 0)  OR  (MOD(YR,400)=0) THEN
                   DBMS_OUTPUT.PUT_LINE(YR || 'IS A LEAP YEAR');
             ELSE
                   DBMS_OUTPUT.PUT_LINE(YR || 'IS NOT A LEAP YEAR');
             END IF;
       END;
   /

Enter value for yr:      1990
old   2:        YR NUMBER(6,2) := &YR;
new   2:        YR NUMBER(6,2) :=        1990;
1990IS NOT A LEAP YEAR

PL/SQL procedure successfully completed.
-----------------------------------------------------------------------------------------------
SQL> /
Enter value for yr: 2000
old   2:        YR NUMBER(6,2) := &YR;
new   2:        YR NUMBER(6,2) := 2000;
2000IS A LEAP YEAR

PL/SQL procedure successfully completed.
-----------------------------------------------------------------------------------------------
SQL> /
Enter value for yr: 1996
old   2:        YR NUMBER(6,2) := &YR;
new   2:        YR NUMBER(6,2) := 1996;
1996IS A LEAP YEAR

PL/SQL procedure successfully completed.
-----------------------------------------------------------------------------------------------
SQL> /
Enter value for yr: 1886
old   2:        YR NUMBER(6,2) := &YR;
new   2:        YR NUMBER(6,2) := 1886;
1886IS NOT A LEAP YEAR

PL/SQL procedure successfully completed.
-----------------------------------------------------------------------------------------------
SQL> /
Enter value for yr: 1992
old   2:        YR NUMBER(6,2) := &YR;
new   2:        YR NUMBER(6,2) := 1992;
1992IS A LEAP YEAR

PL/SQL procedure successfully completed.
-----------------------------------------------------------------------------------------------
SQL> /
Enter value for yr: 1824
old   2:        YR NUMBER(6,2) := &YR;
new   2:        YR NUMBER(6,2) := 1824;
1824IS A LEAP YEAR

PL/SQL procedure successfully completed.


5.    a. For the exercises below, you will require a temporary table to store the results. You can either create the table yourself or run the labAp_05.sql script that will create the table for you. Create a table named TEMP with the following three columns:

b.
>  Write a PL/SQL block that contains two variables, MESSAGE and     DATE_WRITTEN.
> Declare MESSAGE as VARCHAR2 data type with a length of 35 and DATE_WRITTEN as
> DATE data type. Assign the following values to the variables:

Variable Contents
MESSAGE  :  ‘This is my first PL/SQL program’
DATE_WRITTEN : Current date

Store the values in appropriate columns of the TEMP table. Verify your results by querying the TEMP table.

Column Name NUM_STORE CHAR_STORE DATE_STORE


SQL> create table TMP
          (NUM_STORE NUMBER(7,2),
           CHAR_STORE VARCHAR2(35),
           DATE_STORE DATE) ;

Table created.

SQL> DECLARE
     MSG VARCHAR2(35) := 'This is my first PL/SQL program';
     DATE_WRITTEN DATE := SYSDATE;
     BEGIN
        insert into TMP (CHAR_STORE, DATE_STORE) values
        (MSG, DATE_WRITTEN);
     END;
    /

PL/SQL procedure successfully completed.

SQL> select * from tmp;

 NUM_STORE CHAR_STORE                               DATE_STORE
-----------------  ---------------------------------------- -------------------
                      This is my first PL/SQL program   05-OCT-11


7. Write a PL/SQL block to declare a variable called v_salary to store the salary of an employee. In the executable part of the program, do the following:

a. Store an employee name in a iSQL*Plus substitution variable
b. Store his or her salary in the variable v_salary
c. If the salary is less than 3,000, give the employee a raise of 500 and display the message   '<Employee Name>’s salary updated' in the window.
d. If the salary is more than 3,000, print the employee’s salary in the format, '<Employee Name> earns …...………'
e. Test the PL/SQL for the following last names:

SQL> DECLARE
         ENM VARCHAR2(40) := '&EMPLOYEE_NAME';
         SAL NUMBER(7,2) := &SAL;
    BEGIN
          IF SAL < 3000 THEN
              SAL := SAL + 500;
               DBMS_OUTPUT.PUT_LINE('Employee ' || ENM || ' salary is increased '|| SAL);
         ELSE
                DBMS_OUTPUT.PUT_LINE('Employee earns Rs. ' || SAL);
       END IF;
    END;
   /

Enter value for employee_name: PATABELLA
old   2:          ENM VARCHAR2(40) := '&EMPLOYEE_NAME';
new   2:          ENM VARCHAR2(40) := 'PATABELLA';
Enter value for sal: 4800
old   3:          SAL NUMBER(7,2) := &SAL;
new   3:          SAL NUMBER(7,2) := 4800;
Employee earns Rs. 4800

PL/SQL procedure successfully completed.
-----------------------------------------------------------------------------------------------
SQL> /
Enter value for employee_name: Greenburg
old   2:          ENM VARCHAR2(40) := '&EMPLOYEE_NAME';
new   2:          ENM VARCHAR2(40) := 'Greenburg';
Enter value for sal: 12000
old   3:          SAL NUMBER(7,2) := &SAL;
new   3:          SAL NUMBER(7,2) := 12000;
Employee earns Rs. 12000

PL/SQL procedure successfully completed.
-----------------------------------------------------------------------------------------------
SQL> /
Enter value for employee_name: Ernst
old   2:          ENM VARCHAR2(40) := '&EMPLOYEE_NAME';
new   2:          ENM VARCHAR2(40) := 'Ernst';
Enter value for sal: 6000
old   3:          SAL NUMBER(7,2) := &SAL;
new   3:          SAL NUMBER(7,2) := 6000;
Employee earns Rs. 6000

PL/SQL procedure successfully completed.
-----------------------------------------------------------------------------------------------
SQL> /
Enter value for employee_name: Philtanker
old   2:          ENM VARCHAR2(40) := '&EMPLOYEE_NAME';
new   2:          ENM VARCHAR2(40) := 'Philtanker';
Enter value for sal: 2200
old   3:          SAL NUMBER(7,2) := &SAL;
new   3:          SAL NUMBER(7,2) := 2200;
Employee Philtanker salary is incresed Rs. 2700

PL/SQL procedure successfully completed.


8. a. Store the salary of an employee in a iSQL*Plus substitution variable.
b. Write a PL/SQL block to use the above defined salary and perform the following:
• Calculate the annual salary as salary * 12.
• Calculate the bonus as indicated below:
• Display the amount of the bonus in the window in the following format:
‘The bonus is $………………..’
Annual Salary               Bonus
>= 20,000                     2,000
19,999 - 10,000           1,000
<= 9,999                           500

SQL> DECLARE
                 SAL NUMBER(9,2) := &SAL;
                 ASAL NUMBER(9,2);
                 BONUS NUMBER(7,2);
    BEGIN
                ASAL := SAL*12;
     DBMS_OUTPUT.PUT_LINE(ASAL);

      IF (ASAL > 20000) THEN
              BONUS := 2000;
              DBMS_OUTPUT.PUT_LINE('Annual Salary is : '|| ASAL);
              DBMS_OUTPUT.PUT_LINE(' GREATER  THAN 20000 HENCE BONUS = '||BONU
ELSIF (ASAL > 10000) THEN
             BONUS := 1000;
             DBMS_OUTPUT.PUT_LINE('Annual Salary is : '|| ASAL);
             DBMS_OUTPUT.PUT_LINE(' GREATER  THAN 10000 BUT LESS THAN 20000 HENCE BONUS = '||BONUS);
ELSE
              BONUS := 500;
            DBMS_OUTPUT.PUT_LINE('Annual Salary is : '|| ASAL);
            DBMS_OUTPUT.PUT_LINE(' LESS  THAN 10000 HENCE BONUS = '||BONUS);
      END IF;
 END;
    /

Enter value for sal: 5000
old   3:          SAL NUMBER(9,2) := &SAL;
new   3:          SAL NUMBER(9,2) := 5000;
60000
Annual Salary is : 60000
GREATER  THAN 20000 HENCE BONUS = 2000

PL/SQL procedure successfully completed.
-----------------------------------------------------------------------------------------------
SQL> /
Enter value for sal: 1000
old   3:          SAL NUMBER(9,2) := &SAL;
new   3:          SAL NUMBER(9,2) := 1000;
12000
Annual Salary is : 12000
GREATER  THAN 10000 BUT LESS THAN 20000 HENCE BONUS = 1000

PL/SQL procedure successfully completed.
-----------------------------------------------------------------------------------------------
SQL> /
Enter value for sal: 15000
old   3:          SAL NUMBER(9,2) := &SAL;
new   3:          SAL NUMBER(9,2) := 15000;
180000
Annual Salary is : 180000
GREATER  THAN 20000 HENCE BONUS = 2000

PL/SQL procedure successfully completed.


9. a. Write a PL/SQL block to store an employee number, the new department number, and the percentage increase in the salary in iSQL*Plus substitution variables.

b. Update the department ID of the employee with the new department number, and update the salary with the new salary. Use the EMP table for the updates. Once the update is complete, display the message, 'Update complete' in the window. If no matching records are found, display ‘No Data Found’. Test the PL/SQL for the following test cases:

EmpNo
DeptNo
%Increase
Message
7895
20
2
Updation Complete
7772
30
5
No data found
7900
10
3
Updation Complete

DECLARE

          EMPID NUMBER(7,2) := &EMPID;
          NEW_DEPTNO NUMBER(7,2) := &NEW_DEPTNO;
         
BEGIN

          UPDATE EMPLY SET SAL = SAL + (SAL * 00.2 ) WHERE EMPNO = EMPID;
          DBMS_OUTPUT.PUT_LINE(' Salary Updated successfully to '  );
END;

Enter value for empid: 7566
old   3:        EMPID NUMBER(7,2) := &EMPID;
new   3:        EMPID NUMBER(7,2) := 7566;
Enter value for new_deptno: 10
old   4:        NEW_DEPTNO NUMBER(7,2) := &NEW_DEPTNO;
new   4:        NEW_DEPTNO NUMBER(7,2) := 10;
Salary Updated successfully

PL/SQL procedure successfully completed.

DECLARE

          EMPID NUMBER(7,2) := &EMPID;
          NEW_DEPTNO NUMBER(7,2) := &NEW_DEPTNO;
         
BEGIN

          UPDATE EMPLY SET SAL = SAL + (SAL * 00.2 ) WHERE EMPNO = EMPID;
          DBMS_OUTPUT.PUT_LINE(' Salary Updated successfully to '  );
END;

Enter value for empid: 7566
old   3:        EMPID NUMBER(7,2) := &EMPID;
new   3:        EMPID NUMBER(7,2) := 7566;
Enter value for new_deptno: 10
old   4:        NEW_DEPTNO NUMBER(7,2) := &NEW_DEPTNO;
new   4:        NEW_DEPTNO NUMBER(7,2) := 10;

PL/SQL procedure successfully completed.


10. Create a PL/SQL block to declare a cursor EMP_CUR to select the employee name, salary, and hiredate from the EMPLOYEES table. Process each row from the cursor, and if the salary is greater than 15,000 and the hire date is greater than 01-FEB-1988, display the employee name, salary, and hire date in the window.

PL/SQL BLOCK:

declare
          cursor emp_cur is
                   select * from employees;
          emp emp_cur%rowtype;
          n NUMBER(7,2);
begin
          open emp_cur;
          select count(*) into n from employees;
           for i in 1..n loop
                 fetch emp_cur into emp;
                 if(emp.salary > 15000 AND (to_date(emp.hire_date) > to_date('1-feb-1988'))) then
                   dbms_output.put_line(emp.first_name||' earns '||emp.salary||' and joined the organization in '||emp.hire_date);
                 end if;
          end loop;  
          close emp_cur;
end;
/

/*   output

Neena earns 17000 and joined the organization in 21-SEP-89
Lex earns 17000 and joined the organization in 13-JAN-93        */


11. Create a PL/SQL block to retrieve the last name and department ID of each employee from the EMPLOYEES table for those employees whose EMPLOYEE_ID is less than 114. From the values retrieved from the EMPLOYEES table, populate two PL/SQL tables, one to store the records of the employee last names and the other to store the records of their department IDs. Using a loop, retrieve the employee name information and the salary information from the PL/SQL tables and display it in the window, using DBMS_OUTPUT.PUT_LINE. Display these details for the first 15 employees in the PL/SQL tables.


PL/SQL BLOCK

declare
          cursor emp_dept_cur is
                 select * from employees;
          e_dept emp_dept_cur%rowtype;
          n NUMBER(7,2);
begin
          open emp_dept_cur;
          select count(*) into n from employees;
          for i in 1..n loop
                fetch emp_dept_cur into e_dept;              
                if(e_dept.employee_id < 114) then
                   dbms_output.put_line('Employee ID : ' || e_dept.last_name || ' Department ID : ' || e_dept.department_id);
               end if;
          end loop;  
          close emp_dept_cur;
end; 
                  
/

OUTPUT:

Employee ID : King Department ID : 90
Employee ID : Kochhar Department ID : 90
Employee ID : De Haan Department ID : 90
Employee ID : Hunold Department ID : 60
Employee ID : Ernst Department ID : 60
Employee ID : Austin Department ID : 60
Employee ID : Pataballa Department ID : 60
Employee ID : Lorentz Department ID : 60
Employee ID : Greenberg Department ID : 100
Employee ID : Faviet Department ID : 100
Employee ID : Chen Department ID : 100
Employee ID : Sciarra Department ID : 100
Employee ID : Urman Department ID : 100
Employee ID : Popp Department ID : 100

PL/SQL procedure successfully completed.

12. a. Create a PL/SQL block that declares a cursor called DATE_CUR. Pass a parameter of DATE data type to the cursor and print the details of all employees who have joined after that date.
DEFINE P_HIREDATE = 08-MAR-00

b. Test the PL/SQL block for the following hire dates: 08-MAR-00, 25-JUN-97, 28-SEP-98, 07-FEB-99.

 PL/SQL BLOCK

 create or replace procedure Date_cur_proc (d DATE := ‘8-Mar-2000’)
     as
         cursor date_cur is
                select * from employees;
         dt_cur date_cur%rowtype;
      begin
         for dt_cur in date_cur
         loop
                  if(to_date(dt_cur.hire_date) > to_date(d)) then
                   dbms_output.put_line(dt_cur.first_name);
                 end if;
        end loop;
  end;
  /

Procedure created.

// Here it takes date as 8-Mar-2000
SQL> exec Date_cur_proc();
Sundar
Amit
Sundita

PL/SQL procedure successfully completed.

SQL> exec Date_cur_proc('7-Feb-1999');
Donald
Douglas
Luis
Karen
Kevin
Steven
TJ
Ki
Hazel
Gerald
Eleni
Oliver
Danielle
Mattea
David
Sundar
Amit
William
Elizabeth
Sundita
Kimberely
Charles
Martha
Girard
Randall
Vance

PL/SQL procedure successfully completed.

13.  Create a PL/SQL block to promote clerks who earn more than 3,000 to the job title SR CLERK and increase their salary by 10%. Use the EMP table for this practice. Verify the results by querying on the EMP table. Hint: Use a cursor with FOR UPDATE and CURRENT OF syntax.

MY_REMAINDER: In a procedure or cursor to execute DML statements like select, update cursor is must. Without cursor it is not possible.

PL/SQL BLOCK

   declare
      cursor update_cur is
             select  * from employees for update;
      update_ed update_cur%rowtype;
   begin
      open update_cur;
      loop
              exit when update_cur%NOTFOUND;
          fetch update_cur into update_ed;
            if(update_ed.employee_id < 114) then
              update employees set salary = salary + salary * 0.10
    where current of update_cur;
           end if;
      end loop;
      close update_cur;
  end;
 /

PL/SQL procedure successfully completed.

  n Before executing PL/SQL block

select EMPLOYEE_ID, FIRST_NAME, SALARY
 from EMPLOYEES
 where EMPLOYEE_ID < 114;

EMPLOYEE_ID FIRST_NAME           SALARY
------------------- --------------------   ---------------
          100             Steven                  25615.89
          101             Neena                  18144.59
          102             Lex                        18144.59
          103             Alexander            9605.96
          104             Bruce                    6403.98
          105             David                    5123.18
          106             Valli                      5123.18
          107             Diana                    4482.78
          108             Nancy                   12807.95
          109             Daniel                   9605.96
          110             John                      8752.1
          111             Ismael                   8218.43
          112             Jose Manuel         8325.16
          113             Luis                        7364.57

14 rows selected.

         
n After executing PL/SQL block

 select EMPLOYEE_ID, FIRST_NAME, SALARY
 from EMPLOYEES
 where EMPLOYEE_ID < 114;

EMPLOYEE_ID FIRST_NAME           SALARY
------------------- --------------------   ---------------
          100             Steven                  28177.48
          101             Neena                  19959.05
          102             Lex                        19959.05
          103             Alexander            10566.56
          104             Bruce                    7044.38
          105             David                    5635.5
          106             Valli                      5635.5
          107             Diana                    4931.06
          108             Nancy                   14088.75
          109             Daniel                   10566.56
          110             John                      9627.31
          111             Ismael                   9040.27
          112             Jose Manuel         9157.68
          113             Luis                        8101.03

14 rows selected.

MY_REMAINDER:

SQL Bind Variables

<SQL> variable v varchar2(20);
 <SQL> begin
                   :v := 5;
               dbms_output.put_line(' The value of the sql bind variable or global variable v is = ‘|| :v);
          end;
  /
The value of the sql bind variable v is : 5

PL/SQL procedure successfully completed.


14. a. For the exercise below, you will require a table to store the results. You can create the ANALYSIS table yourself or run the labAp_14a.sql script that creates the table for you. Create a table called ANALYSIS with the following three columns:
Column Name : ENAME YEARS SAL

b. Create a PL/SQL block to populate the ANALYSIS table with the information from the EMPLOYEES table. Use an iSQL*Plus substitution variable to store an employee’s last name.

c. Query the EMPLOYEES table to find if the number of years that the employee has been with the organization is greater than five, and if the salary is less than 3,500, raise an exception. Handle the exception with an appropriate exception handler that inserts the following values into the ANALYSIS table: employee last name, number of years of service, and the current salary. Otherwise display Not due for a raise in the window. Verify the results by querying the ANALYSIS table. Use the following test cases to test the PL/SQL block:

LAST_NAME               MESSAGE
                                  Not due for a raise
Nayer                        Not due for a raise
Fripp                         Not due for a raise
Khoo                         Due for a raise

Ø CODE

SQL> create table ANALYSIS
          (ENAME VARCHAR2(20), YEARS NUMBER(2), SAL NUMBER(8,2));

Table created.

 /* This sql code is stored in plexe14.txt file */
SQL> declare
  2     CURSOR emp_cur is
  3             select * from employees;
  4     emp emp_cur%rowtype;
  5
  6     CURSOR ana_cur is
  7             select * from analysis;
  8     ana ana_cur%rowtype;
         
          /* user defined exception declaration*/
  9     still_low_sal EXCEPTION;
 10
 11     lstnm VARCHAR2(35) := &Employee_Last_Name;
 12     swt NUMBER(2) := 0;
 13  begin
 14                 open emp_cur;
 15     loop
 16             exit when emp_cur%NOTFOUND;
 17                                   fetch emp_cur into emp;

                   /* MY_REMAINDER: These comments will be first removed to insert records into analysis table using employee table. No need to run it every time, hence the code is commented.  */

 18     /*              insert into analysis(ename) values(emp.fname);   */
 19        /*   update analysis set years = floor(months_between(to_date(SYSDATE),to
_date(emp.HIRE_DATE))/12) where ename = emp.fname; */
 20         /*        update analysis set sal = emp.salary where  ename = emp.first_
name;   */
 21     end loop;
 22                 close emp_cur;
 23     open ana_cur;
 24     loop
 25             exit when ana_cur%NOTFOUND;
 26             fetch ana_cur into ana;
 27             /*         dbms_output.put_line(ana.years || ana.sal);   */
 28              if(ana.ename = lstnm) then
 29                      swt := 1;
 30                      if(ana.years > 5 AND ana.sal < 3000) then
 31                     RAISE still_low_sal;
 32                      else
 33                     dbms_output.put_line('Not due for a raise');
 34                     end if;
 35             end if;
 36     end loop;
 37
 38     if(swt = 0) then
 39             dbms_output.put_line('Employee not found');
 40     end if;
 41
 42                 close ana_cur;
 43  EXCEPTION
 44     WHEN still_low_sal THEN
 45              dbms_output.put_line('Exception still_low_sal : The employee must g
et salary increment');
 46  end;


 48  /
Enter value for employee_last_name: 'Donald'
old  11:        lstnm VARCHAR2(35) := &Employee_Last_Name;
new  11:        lstnm VARCHAR2(35) := 'Donald';
Exception still_low_sal : The employee must get salary increment

PL/SQL procedure successfully completed.

SQL> /
Enter value for employee_last_name: 'Susan'
old  11:        lstnm VARCHAR2(35) := &Employee_Last_Name;
new  11:        lstnm VARCHAR2(35) := 'Susan';
Not due for a raise

PL/SQL procedure successfully completed.

SQL> /
Enter value for employee_last_name: 'Girard'
old  11:        lstnm VARCHAR2(35) := &Employee_Last_Name;
new  11:        lstnm VARCHAR2(35) := 'Girard';
Exception still_low_sal : The employee must get salary increment

PL/SQL procedure successfully completed.

SQL> /
Enter value for employee_last_name: 'Austin'
old  11:        lstnm VARCHAR2(35) := &Employee_Last_Name;
new  11:        lstnm VARCHAR2(35) := 'Austin';
Employee not found

PL/SQL procedure successfully completed.


16. In this practice, create a program to add a new row to the JOB_HISTORY table for an existing employee.
Note: Disable all triggers on the EMPLOYEES, JOBS, and JOB_HISTORY tables before invoking the procedure in part b. Enable all these triggers after executing the procedure.

a. Create a stored procedure called ADD_JOB_HIST to enter a new row into the JOB_HISTORY table for an employee who is changing his job to the new job ID that you created in question 15b. Use the employee ID of the employee who is changing the job and the new job ID for the employee as parameters. Obtain the row corresponding to this employee ID from the
EMPLOYEES table and insert it into the JOB_HISTORY table. Make hire date of this employee as the start date and today's date as end date for this row in the JOB_HISTORY table. Change the hire date of this employee in the EMPLOYEES table to today's date. Update the job ID of this employee to the job ID passed as parameter (Use the job ID of the job created in question 15b) and salary equal to minimum salary for that job ID + 500. Include exception handling to handle an attempt to insert a nonexistent employee.

b. Disable triggers (Refer to the note at the beginning of this question.)
Execute the procedure with employee ID 106 and job ID SY_ANAL as parameters. Enable the triggers that you disabled.

c. Query the tables to view your changes, and then commit the changes.

PL/SQL BLOCK:

SQL> alter trigger UPDATE_JOB_HISTORY disable;

Trigger altered.

Procedure
create or replace procedure add_job_hist_proc(empid VARCHAR2,jobid VARCHAR2)
  as
           cursor emp_rec is
                   select * from employees for update;
           emp emp_rec%rowtype;
          
           cursor job_rec is
                  select * from jobs;
           job job_rec%rowtype;
             s NUMBER(8,2);
  begin
     open job_rec;
     loop
             exit when job_rec%NOTFOUND;
             fetch job_rec into job;
             if(job.job_id = 'SY_ANAL') then
                     s :=  job.min_salary + 500;
             end if;
     end loop;
     close job_rec;
          
      open emp_rec;
           loop
                    exit when emp_rec%NOTFOUND;
                 fetch emp_rec into emp;
                  if(emp.employee_id = empid) then
                           insert into JOB_HISTORY values(emp.employee_id, emp.hire_date, sysdate, emp.job_id, emp.department_id);
                           update EMPLOYEES set HIRE_DATE = SYSDATE, job_id ='SY_ANAL', salary = s where current of emp_rec;
                 end if;
         end loop;
        close emp_rec;
 end;

/

SQL> exec add_job_hist_proc(105,'IT_PROG');

PL/SQL procedure successfully completed.

SQL> select * from job_history;

EMPLOYEE_ID START_DAT  END_DATE    JOB_ID     DEPARTMENT_ID
----------- --------- --------- ---------------------------------------- -------------
        105              07-MAY-09    13-OCT-11          SY_ANAL               60
        102              13-JAN-93      24-JUL-98             IT_PROG               60
        101              21-SEP-89      27-OCT-93 AC_ACCOUNT    110
        101              28-OCT-93     15-MAR-97          AC_MGR             110
        201              17-FEB-96      19-DEC-99           MK_REP                20
        114              24-MAR-98    31-DEC-99 ST_CLERK              50
        122              01-JAN-99      31-DEC-99 ST_CLERK              50
        200              17-SEP-87      17-JUN-93            AD_ASST               90
        176              24-MAR-98    31-DEC-98 SA_REP                  80
        176              01-JAN-99      31-DEC-99 SA_MAN                80
        200              01-JUL-94       31-DEC-98 AC_ACCOUNT      90

11 rows selected.

SQL> select employee_id, first_name, hire_date, salary, job_id
  2  from employees
  3  where employee_id = 105;

EMPLOYEE_ID FIRST_NAME           HIRE_DATE  SALARY JOB_ID
----------- -------------------- --------- ---------- --------------------------
        105              David                     13-OCT-11       6500  SY_ANAL