0% found this document useful (0 votes)
75 views

PLSQL

This document contains examples of PL/SQL code for declaring variables, writing executable statements, and interacting with the Oracle server database. It demonstrates how to declare variables of different data types, evaluate variable declarations and assignments, use scope and nested blocks, pass values between PL/SQL and iSQL*Plus variables, select, insert, update and delete data from database tables, and commit transactions. Examples include declaring variables, assigning values, selecting max IDs, inserting new records, updating records, and deleting records from database tables.

Uploaded by

Labesh Sharma
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
75 views

PLSQL

This document contains examples of PL/SQL code for declaring variables, writing executable statements, and interacting with the Oracle server database. It demonstrates how to declare variables of different data types, evaluate variable declarations and assignments, use scope and nested blocks, pass values between PL/SQL and iSQL*Plus variables, select, insert, update and delete data from database tables, and commit transactions. Examples include declaring variables, assigning values, selecting max IDs, inserting new records, updating records, and deleting records from database tables.

Uploaded by

Labesh Sharma
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 48

CHAPTER : 01

Declaring Variables
1. Evaluate each of the following declarations. Which of them are not legal
and explain why.
a. DECLARE
V_id NUMBER(4);

Legal
b. DECLARE
V_x ,v_y , v_z VARCHAR2(10);
Illegal Because only one identifier per declaration is
allowed.

c. DECLARE
V_birthdate DATE NOT NULL;

Illegal Because the NOT NULL variable must be initialized .


d. DECLARE
V_in_stock BOOLEAN :=1;

Illegal Because 1 is not a BOOLEAN Expression.

2. In each of the following assignments, indicates whether the statement is


valid and what the valid data type of the result will be .
a. V_days_to_go := v_due_date – SYSDATE;
Valid ; NUMBER
b. V_sender := USER || ‘ : ‘|| TO_CHAR(v_dept_no);
Valid ; Character String
c. v_sum := $100,000+$250,000;
illegal ; PL / SQL can not convert special symbols from
VARCHAR2 to NUMBER

d. v_flag := TRUE;
Valid : BOOLEAN
e. v_nl := v_n2> (2* v_n3);
Valid ; BOOLEAN
f. v_value := NULL;
Valid ; any scalar data type.

3. Create a anonymous block to output the phrase


“My PL/SQL Block Works” to screen.

VARIABLE g_message VARCHAR2(40);


DECLARE

v_message VARCHAR2(40);

BEGIN

v_message := 'MY PL/SQL Block Works';


:g_message := v_message;
END;
/
PRINT g_message

4. Create a block that declares two variables. Assign the values of these
PL/SQL variables to iSQL*Plus host variables and print the result of the
PL/SQL variables to the screen.
V_CHAR Character (variable length)
V_NUM Number
Assign values to these variables as followes
Variable values
----------- -------------------------------------------------------------------------------
V_CHAR The literal ’42 is the answer’
V_NUM The first two Characters from V_CHAR
VARIABLE g_char VARCHAR2(40)
VARIABLE g_num NUMBER
DECLARE
v_char VARCHAR2(40);
v_num NUMBER (10,2);
BEGIN
v_char := ’42 is the answer’;
v_num:=42;
:g_char :=v_char;
:g_num :=v_num;
END;
/
PRINT g_char
PRINT g_num
CHAPTER NO : 02
Write Executable Statements
PL/SQL BLOCK
DECLARE

v_weight NUMBER(3) :600;

v_message VARCHAR2(255) := ‘product 10012’;

BEGIN

DECLARE

v_weight NUMBER(3) :=1;

v_message VARCHAR2(255) :=’product 11001’;

v_new_icon VARCHAR2(50) := ‘Eutope’;

BEGIN

v_weight :=v_weight+1;

v_new_icon := ‘Western’ || v_new_icon;

END;

v_weight :=v_weight+1;

v_message :=‘Western’ || ‘ is in stock’;

v_new_icon := ‘Western’ || v_new_icon;

END;

1. Evaluate the PL/SQL block above and determine the data type and
values of each of the following variables according to the rules of
scoping.
a. The value of V_WEIGHT at the position 1 is.

2 THE data type is NUMBER


b. The value of V_NEW_LOC at position 1 is .

Western Europe The data type is VARCHAR2


c. The value of V_WEIGHT at position 2 is .
601 The data type is NUMBER
d. The value of V_MESSAGE at position 2 is.
Product 10012 is in Stock The data type is VARCHAR2

e. The value of V_NEW_LOC at position 2 is.


Illegal Becausev_new_loc is not visible outside the block.

2. Scope Example
DECLARE
v_customer VARCHAR2(50) := ‘Womansport’;
v_credit_rating VARCHAR2(50) := ‘ EXCELLENT’;
BEGIN

DECLARE
v_customer NUMBER(7):=201;
v_name VARCHAR2(25) := ‘Unisport’;
BEGIN
v_customerv_name v_credit_rating
END;
v_customerv_name v_credit_rating
END;
\
Suppose you embed a subblock within a block as shown
above. You declare two variables V_CUSTOMER and
V_CREDIT_RATING, in the main block. You also declare two
variables V_CUSTOMER and V_NAME, in the subblock.
Determine the values and data types for each of the
following cases.
a. The value of V_CUSTOMER in the subblock is.
201 the data type is NUMBER
b. The value of V_NAME in the subblock is.
UNISPORT and
The data type is VARCHAR2
c. The value of V_CREDIT_RATING in the subblock is.
EXCELLENGT
The data type is VARCHAR2
d. The value of V_CUSTOMER in the block is.
Womansport the data type is VARCHAR2
e. The value of V_NAME in the block is.
V_NAME is not visible in the main block and you
would see an erroe.
f. The value of V_CREDIT_RATING in the main block is.
EXCELLENT The data type is VARCHAR2

3. Createand execute a PL/SQL block that accepts two numbers through


iSQL*Plus substitution variables.

(a) Use the DEFINE command to provide the two values.


DEFINE p_num1 =2
DEFINE p_num2 =4
(b) Pass the two values defined in step a above, to the PL/SQL
block through iSQL*Plus substitution variables. The first
number should be divided by the second number and have the
second number added to the result should be stored in a
PL/SQL variable and printed on the screen.
SET ECHO OFF
SET VARIFY OFF
SET SERVEROUTPUT ON
DEFINE p_num1= 2
DEFINE p_num2 =4
DECLARE
V_num1 NUMBER(9,2) := &p_num1;
V_num2 NUMBER(9,3):=&p_num2;
V_result NUMBER(9,3) ;
BEGIN
V_resutl := (V_num1/ V_num2) + V_num2;
DBMS_OUTPUT.PUT_LINE(V_result);
END;
/
SET ECHO ON
SET VARIFY ON
SET SERVEROUTPUT OFF

4. Build a PL/SQL block that computes the total compensation for one
year.
a. The annual salary and the annual bonus percentage values are
defined using the DEFINE command.
b. Pass the values defined in the above step to the PL/SQL block
through iSQl*Plus substitution variables. The bonus must be
converted from a whole number to a decimal. if the salary is null
set it zero before computing the total compensation. Execute the
PL/SQL block.
NOTE: total compensation is the sum of the annual salary and
annual bonus.
To test the NVL function, set the DEFINE variable equal to NULL.

DEFINE p_salary = 5000


DEFINE p_bonus= 10

SET VARIFY OFF


SET SERVEROUTPUT ON
DEFINE p_salary =5000
DEFINE p_bonus =10
DECLARE
V_salaryNUMBER :=&p_salary;
V_bonusNUMBER :=&p_bonus;
BEGIN
Dbms_output.put_line (TO_CHAR(NVL (v_salary,0)*(1+NVL
(V_bonus,0)/10)));

END;
/

SET VARIFY ON
SET SERVEROUTPUT OFF
CHAPTER : 03
Interacting With the oracle Server
1. Create a PL/SQL block that selects the maximum department number in
the DEPARTMENTS table and stores it in an iSQL*Plus variable. Print the
result to the screen. Save your PL/SQL block in a file named plsql.sql. by
clicking the save script button.
VARIABLE g_max_deptno NUMBER
DECLARE
v_max_deptno NUMBER;

BEGIN
SELECT max(department_id)
INTO v_max_deptno
FROM departments;
:g_max_deptno := v_max_deptno;

END;
/
PRINT g_max_deptno

2. Modify the PL/SQL block you created in exercise 1 to insert a new


department into the DEPARTMENTS table. Save the PL/SQL block in a file
named plsql2.sql. by clicking the save script button.

a. Use the DEFINE command to provide the department name. name


the new department EDUCATION.
b. Pass the values defined for the department name to the PL/SQL
block through aiSQL*Plus substitution variables. Rather than
printing the department number retrieved from exercise 1 add 10
to it and use it as department number for the new department.
c. Leave the location number as null for now.

SET ECHO OFF


SET VERIFY OFF
DEFINE p_dname = EDUCATION
DECLARE
v_max_deptnodepartments.department_id%TYPE;
BEGIN
SELECT max (department_id)+10
INTO v_max_deptno
FROM departments;
INSERT INTO departments (department_id, department_name, location_id)
VALUES(v_max_deptno ,'&p_dname',NULL );
COMMIT;
END;
/
SET VERIFY ON
SET ECHO ON

d. Execute the Pl/SQL block


e. Display the new department that you created.
SELECT *
FROM departments
WHERE department_name ='EDUCATION';

3. Create a PL/SQL block that updates the location ID for the new
department that you added in the previous practice. Save your PL/SQL
block in a file named plsql3.sql. bu clicking the save script button.
a. Use an Isql*Plus variable for the department ID number that you added
in the previous practice.
b. Use the DEFINE command to provide the location ID.name the new
location ID 1700.
DEFINE p_deptno=280
DEFINE p_loc =1700
c. Pass the value to the PL/SQL block through Isql*Plus substitution
variable. Test the Pl/SQL block.

SET VERIFY OFF


DEFINE p_deptno=280
DEFINE p_loc= 1700
BEGIN
UPDATE departments
SET Location_id = &p_loc
WHERE department_id = &p_deptno;
COMMIT;
END;
/
SET VERIFY ON
d. Display the department that you updated.
SELECT *
FROM departments
WHERE department_id= &p_deptno;

4. Createa PL/SQL block that deletes the department that you created in
exercise 2. Save the PL/SQL block in a file named plsql3.sql .
a. Use the DEFINE command to provide the department ID
DEFINE p_deptno= 280
b. Pass the values to the PL/SQL block through aIsql*Plus substitution
variable. Print to the screen the number of rows affected.
SET VERIFY OFF
VARIABLE g_resultVARCHAR2(40)
DEFINE p_deptno=280
DECLARE
v_result NUMBER(2);
BEGIN
DELETE
FROM departments
WHERE department_id= &p_deptno;
v_result := SQL%ROWCOUNT;
:g_result :=(TO_CHAR(v_result)||'rows deleted.');
COMMIT;
END;
/
PRINT g_result
SEt VERIFY ON

c. Test the PL/SQL block .


SELECT *
FROM departments
WHERE department_id=280;
CHAPTER : 04
Writing Control Structures
1. Execute the command in the file lab04.sql to create the MESSAGES
tables. Write a PL/SQL block to insert number into the MESSAGES
table.

CREATE TABLE message (results VARCHAR(60));


a. Insert the numbers 1 to 10 excluding 6 and 8 .
b. Commit before the end of the block.
BEGIN
FOR I in 1..10 LOOP
IF I=6 OR I=8 ThEN
NULL;
ELSE
INSERT INTO message (results)
VALUES(i);
END IF;
COMMIT;
END LOOP;
END;
/
c. Select from the MESSAGES table to verify that your PL/SQL block
worked.
SELECT *
FROM message;
2. Create a PL/SQL block that computes the commission amount for a
given employee based on the employee’s salary
a. Use the DEFINE command to provide the employee ID. Pass the value to
th PL/SQL block through isql*plus substitution variable.
DEFINE p_empno=100
b. If the employee’s salary is less than $5,000 display the bonus amount for
the employee as 10% of the salary.
c. If the employee’s salary between $5,000 and $10,000 display the bonus
amount for the employee as 15% of the salary.
d. If the employee’s salary exceeds $10,000, display the bonus amount for
the employees as 20% of the salary.
e. If the employee’s salary is NULL, display the bonus amount for
employees as for 0.
f. Test the PL/SQL block for each case using the following test case and
check each bonus amount.
SET SERVEROUTPUT ON
SET VERIFY OFF
DEFINE p_empno =100
DECLARE
v_empnoemployees.employee_id%TYPE :=&p_empno;
v_salemployees.salary%TYPE;
v_bonus_per NUMBER (7,2);
v_bonus NUMBER(7,2);
BEGIN
SELECT salary
INTO v_sal
FROM employees
WHERE employee_id =v_empno;
IF v_sal<5000 THEN
v_bonus_per := .10;
ELSIF v_sal BETWEEN 5000 AND 10000 THEN
v_bonus_per := .15;
ELSIF v_sal> 10000 THEN
v_bonus_per := .20;
ELSE
v_bonus_per:=0;
END IF;
v_bonus := v_sal *v_bonus_per;
DBMS_OUTPUT.PUT_LINE('The bonus for the employees with employee_id
'||v_empno||'and salary'||v_sal ||' is'||v_bonus);
END;
/
3. Create an EMP table that is a replica of the EMPLOYEES table. You
can do this by executing the script lad04_3.sql. add a new column
STARTS of VARcHAR2 data type and the length of 50 to the EMP table
for sorting asterisk (*).
ALTER TABLE emp
ADD stars VARCHAR(50);
4. Create a PL/SQL block that rewards an employee by appending an
asterisk in the STARS column for every $1,000 of the employee’s
salary.
a. Use DEFINE command to provide the employee ID. Pass the value
to the PL/SQL block through isql*plus substitution variable.
DEFINE p_empno=104
b. Initialize a v_asterisk variable that contains a Null.
c. Append an asterisk to the string for every $1000 of the salary
amount. For example if the employee has a salary amount of
$8000 the string of asterisk should be contain eight asterisk. If the
employee has a salary amount of $12500 the string of asterisk
should be contain 13 asterisks.
d. Update the STARS column for the employee with the string of
asterisk.
e. Commit.
f. Test the for the following values.
DEFINE p_empno=174
DEFINE p_empno=176
SET VERIFY OFF
DEFINE p_empno=174
DECLARE
v_empemp.employee_id%TYPE :=TO_NUMBER(&p_empno);
v_asteriskemp.stars%TYPE :=NULL;
v_salemp.salary%TYPE;
BEGIN
SELECT NVL(ROUND(salary/1000),0)
INTO v_sal
FROM
emp
WHERE employee_id =v_empno;
FOR I IN 1..v_sal LOOP
v_asterisk :=v_asterisk || '*';
END LOOP;
UPDATE emp
SET stars =v_asterisk
WHERE employee_id =v_empno;
COMMIT;
END;
/
SET VERIFY ON

g. Display the rows from the EMP table to verify whether your
PL/SQL block has executed successfully.

SELECT id,salary , stars


FROM emp
WHERE id=174;
CHAPTER : 05
Working With Composite Data Types
1. Write a PL/SQL block to print information about a given country
a. Declare a PL/SQL record based on the structure of the COUNTRIES table.
b. Use the DEFINE command to provide the country ID. Pass the values to
the PL/SQL block through aisql*Plus substitution variable.
c. Use DBMS_OUTPUT.PUT_LINE to print selected information about the
country. A sample output is shown below.
Country Id: CA Country Name : Canada Region :2
SET SERVEROUTPUT ON
SET VERIFY OFF
DEFINE p_countryid = CA
DECLARE
country_recordcountries%ROWTYPE;
BEGIN
SELECT *
INTO country_record
FROM countries
WHERE country_id =UPPER('&p_countryid');
DBMS_OUTPUT.PUT_LINE('country_id:'||
country_record.country_id||'Country_Nmae:'||country_reco
rd.country_name||'Region:'||country_record.region_id);
END;
/
SET SERVEROUTPUT OFF

d. Execute and test the Pl/SQL block for the countries with the IDs CA, DE,
Uk, US.

2. Create a PL/SQL block to retrieve the name of each department from the
DEPARTMENTS table and print each department name on the screen,
incorporating an INDEX BY table. Save the code in a file called plsql4.sql.
a. Declare an INDEX BY table, MT_DEPT_TABLE to temporary store the
name of the departments.
b. Using a loop, retrieve the name of all departments currently in the
DEPARTMENTS table and store them in the INDEX BY table. Use the
following table to assign the values for DEPARTMENT_ID based on
the value of the counter used in the loop
COUNTER DEPARTMENT_ID
1 10
2 20
3 50
4 60
5 80
6 90
7 110
SET SERVEROUTPUT ON
DECLARE
TYPE DEPT_TABLE_TYPE IS table of departments.department_name%TYPE
INDEX BY BINARY_INTEGER;
my_dept_tabledept_table_type;
v_count NUMBER(2);
v_deptnodepartments.department_id%TYPE;
BEGIN
SELECT COUNT(*) INTO v_count FROM departments;
FOR I IN 1..v_count
LOOP
IF I=1 THEN
v_deptno:=10;
ELSIF 1=2 THEN
v_deptno:=20;
ELSIF I=3 THEN
v_deptno:=50;
ELSIF I=4 THEN
v_deptno:=60;
ELSIF 1=5 THEN
v_deptno:=80;
ELSIF I=6 THEN
v_deptno:=90;
ELSIF I=7 THEN
v_deptno:=110;
END IF;
SELECT department_name INTO my_dept_table(I) FROM departments
WHERE department_id = v_deptno;
END LOOP;
FOR I IN 1..v_count
LOOP
DBMS_OUTPUT.PUT_LINE(my_dept_table(I));
END LOOP;
END;
/
SET SERVEROUTPUT OFF

3. Modify the block you created in practice 2 to retrieve all information


about each department from the departments table and print the
information to the screen incorporating in INDEX BY table of record.
a. Declare an INDEX BY table, MY_DEPT_TABLE, to temporaritly to store
the number, name and location of all the departments
b. Using a loop, retrieve all department information currently in the
DEPARTMENTS table and store it in the INDEX BY table. Use the
following table to assign the values for DEPARTMENT_ID based on the
value of the counter used in the loop. Exit the loop when then counter
reaches the value 7.
COUNTER DEPARTMENT_ID
1 10
2 20
3 50
4 60
5 80
6 90
7 110

c. Using another loop, retrieve the department information from the


INDEX BY table and print it to the screen, using
DBMS_OUTPUT.PUT_LINE

SET SERVEROUTPUT ON
DECLARE
TYPE DEPT_TABLE_TYPE IS table of departments%ROWTYPE INDEX
BY BINARY_INTEGER;
my_dept_tabledept_table_type;
v_deptnodepartments.department_id%TYPE;
v_count NUMBER :=7;
BEGIN
SELECT COUNT(*) INTO v_count FROM departments;
FOR I IN 1..v_count
LOOP
IF I=1 THEN
v_deptno:=10;
ELSIF 1=2 THEN
v_deptno:=20;
ELSIF I=3 THEN
v_deptno:=50;
ELSIF I=4 THEN
v_deptno:=60;
ELSIF 1=5 THEN
v_deptno:=80;
ELSIF I=6 THEN
v_deptno:=90;
ELSIF I=7 THEN
v_deptno:=110;
END IF;
SELECT *
INTO my_dept_table(I) FROM departments
WHERE department_id = v_deptno;
END LOOP;
FOR I IN 1..v_count
LOOP
DBMS_OUTPUT.PUT_LINE('Department Number:' ||
my_dept_table(I).department_id||'Department Name:'||
my_dept_table(I).department_name || 'Manager ID:'||
my_dept_table(I).manager_id|| 'Location Id:'||
my_dept_table(I).location_id);
END LOOP;
END;
/
CHAPTER : 06
Writing Explicit Cursors
1. Run the command in the script lab06_1.sql to create a new table for
sorting the salaries of the employees.

CREATE TABLE top_dogs


(name VARCHAR2(25), salary NUMBER(8,2));
2. Create a PL/SQL block that determines the top employees with respect
to salaries.
a. Accept a number n from the user where n represents the number of top
n earners from the EMPLOYEES table.
b. In a loop use the isql*plus substitution parameter created in step 1 and
gather the salaries of the top n people from the EMPLOYEES table. There
should be no duplication salaries. If two employees earn the same
salary, the salary should be picked up only once.
c. Store the salaries in the TOP_DOGS table.
d. Test a variety of special cases, such as n=0 or where n is greater than
the number of employees in the EMPLOYEES table. Empty the
TOP_DOGS table after each case. The output shown represents the five
hioghest salaries in the EMPLOYEES table
DELETE FROM top_dogs;
DEFINE p_num=5
DECLARE
v_num NUMBER(3) :=&p_num;
v_salemployees.salary%TYPE;
CURSOR emp_cursor IS
SELECT distinct salary
FROM employees
ORDER BY salary DESC;
BEGIN
OPEN emp_cursor;
FETCH emp_cursor INTO v_sal;
WHILE emp_cursor%ROWCOUNT<=v_num AND emp_cursor%FOUND
LOOP
INSERT INTO top_dogs(salary)
VALUES(v_sal);
FETCH emp_cursor INTO v_sal;
END LOOP;
ClOSEemp_cursor;
COMMIT;
END;
/
SELECT * FROM top_dogs;
3. Create a PL/SQL block that does the following
a. Use DEFINE command to provide the department ID. Pass the value
to the Pl/SQL block through aisql*Plus substitution variable.
b. In a Pl/SQL block, retrieve the last name, salary, and MANAGER ID of
the employees working in that department.
c. If the salary of the employees is less than 5000 and if the manager id
id either 101 or 124, display the message <<last name >> Due for a
raise. Otherwise, display the message <<last name >> not due for a
raise.

d. Test the PL/SQL block for the following cases.


DEPARTMENT ID MESSAGE
10 Whalen Due for a raise
20 Hartstein Not Due for a raise
Pay NOT Due for a raise
50 Weiss NOT Due for a raise
Fripp Due for a raise
Kaufling Due for a raise
Vollman Due for a raise
Mourges Due for a raise
...
...
80 Russel NOT Due for a raise
Partners NOT Due for a raise
Errazuriz NOT Due for a raise
Combrault NOT Due for a raise
...
...

SET SERVEROUTPUT ON
SET ECHO OFF
DEFINE p_dept_no =10
DECLARE
v_deptno NUMBER(4) :=(&p_dept_no);
v_enameemployees.last_name%TYPE';
v_salemployees.salary%TYPE;
v_manageremployees.manager_id%TYPE;
CURSOR emp_cursor IS
SELECT last_name, salary ,manager_id
FROM employees
WHERE department_id =v_deptno;
BEGIN
OPEN emp_cursor;
FETCH emp_cursor INTO v_ename, v_sal,
v_manager;
WHILE emp_cursor%FOUND LOOP
IF v_sal<5000 AND (v_manager=101 OR
v_manager=124) THEN
DBMS_OUTPUT.PUT_LINE (v_ename || 'Due for a
raise');
ELSE

DBMS_OUTPUT.PUT_LINE (v_ename || 'NOT Due


for a raise');
END IF;
FETCH emp_cursor INTO v_ename ,v_sal ,
v_manager;
END LOOP;
CLOSE emp_cursor;
END;
/
SET SERVEROUTPUT OFF
CHAPTER : 07
Advance Explicit Cursor Concepts

1. In a loop, use a cursor to retrieve the department number and the


department name from the DEPARTMENTS table for those departments
whose DEPARTMENT_ID is less than 100. Pass the department number
to another cursor to retrieve from the EMPLOYEES table the details of
employee last name, job, hire date, and salary of those employees
whose EMPLOYEE_ID is less than 120 and who work in that department.

SET SERVEROUTPUT ON
DECLARE
CURSOR dept_cursor IS
SELECT department_id, department_name
FROM departments
WHERE department_id<100
ORDER BY department_id;
CURSOR emp_cursor(v_deptno NUMBER) IS
SELECT last_name, job_id, hire_date, salary
FROM employees
WHERE department_id=v_deptno
AND employee_id<120;
v_current_deptnodepartments.department_id%TYPE;
v_current_dnamedepartments.department_name%TYPE;
v_enameemployees.last_name%TYPE;
v_jobemployees.job_id%TYPE;
v_hiredateemployees.hire_date%TYPE;
v_salemployees.salary%TYPE;
v_linevarchar2(100);
BEGIN
v_line :=' ' ;
OPEN dept_cursor;
LOOP
FETCH dept_cursor INTO
v_current_deptno, v_current_dname;
EXIT WHEN dept_cursor%NOTFOUND;
DBMS_OUTPUT.PUT_LINE('Department Number:'||
v_current_deptno|| 'Department Name'|| v_current_dname);

DBMS_OUTPUT.PUT_LINE(v_line);
IF emp_cursor%ISOPEN THEN
CLOSE emp_cursor;
END IF;
OPEN emp_cursor (v_current_deptno);
LOOP
FETCH emp_cursor INTO
v_ename, v_job, v_hiredate, v_sal;
EXIT WHEN emp_cursor%NOTFOUND;
DBMS_OUTPUT.PUT_LINE(v_ename||' '|| v_job || ' ' ||
v_hiredate || ' ' || v_sal);
END LOOP;
IF emp_cursor%ISOPEN THEN
CLOSE emp_cursor;
END IF;
DBMS_OUTPUT.PUT_LINE(v_line);
END LOOP;
IF emp_cursor%ISOPEN THEN
CLOSE emp_cursor;
END IF;
CLOSE dept_cursor;
END;
/
SET SERVEROUTPUT OFF

2. Modify the code in sol04.sql to incorporate a cursor using the FOR


UPDATE and WHERE CURRENT OF functionality in cursor processing.
SET VERIFY OFF
DEFINE p_empno =104
DECLARE
v_empnoemp.id%TYPE :=&p_empno;
v_asteriskemp.stars%TYPE :=NULL;
CURSOR emp_cursor IS
SELECT id, NVL(ROUND(salary/1000),0) sal
FROM emp
WHERE id=v_empno
FOR UPDATE;
BEGIN
FOR emp_record IN emp_cursor LOOP
FOR I IN 1..emp_record.sal LOOP
v_asterisk :=v_asterisk || '*';
DBMS_OUTPUT.PUT_LINE(v_asterisk);
END LOOP;
UPDATE emp
SET stars =v_asterisk
WHERE CURRENT OF emp_cursor;
v_asterisk :=NULL;
END LOOP;
COMMIT;
END;
/
SET VERIFY ON
Execute the following command to check if your PL/SQL block has
worked successfully;
SELECT id, salary, stars
FROM emp
WHERE id IN(176,174,104);
CHAPTER : 08
Handling Exceptions

1. Write a PL/SQL block to select the name of the employee with a given
salary value.
a. Use the DEFINE command to provide the salary. Pass the value to the
PL/SQL block through aisql*plus substitution variable. If the salary
entered returns more than one row, handle the exception with an
appropriate exception handler and insert into the MESSAGES table
the message “More than one employee with a salary of <salary>.”
b. If the salary entered does not return any row, handle the exception
with an appropriate exception handler and insert into the MESSAGE
table the message “No employee with a salary of <salary>”
c. If the salary entered returns only one row, insert into the MESSAGES
table the employee’s name and the salary amount.
d. Handle any other exception with an appropriate exception handler
and insert into the MESSAGES table the message “Some other error
occured”.
e. Test the block for a variety of test cases. Display the rows form the
MESSAGES table to check whether the PL/SQL block has executed
successfully.
SET VERIFY OFF
DEFINE p_sal =6000
DECLARE
v_enameemployees.last_name%TYPE;
v_salemployees.salary%TYPE :=&p_sal;
BEGIN
SELECT last_name
INTO v_ename
FROM employees
WHERE salary= v_sal;
INSERT INTO messages (results)
VALUES (v_ename || ' -' || v_sal);
EXCEPTION
WHEN no_data_found then

INSERT INTO messages (results)


VALUES ('NO employee with a salary of' || TO_CHAR (v_sal));
WHEN too_many_rows THEN
INSERT INTO messages (results)
VALUES ('More than one employee with a salary'|| TO_CHAR (v_sal));
WHEN others THEN
INSERT INTO messages (results)
VALUES('Some other error occured');
END;
/
SET VERIFY ON
2. Modify the code plsql3.sql to add an exception handler.
a. Use DEFINE command to provide the department ID and department
location. Pass the values to the PL/SQL block through aisql*Plus
substitution variable.
b. Write an exception handler for the error to pass a message to the user
that the specified department does not exist. Use a bind variable to pass
the message to the user.
c. Execute the PL/SQL block by entering a department that does not exist.

SET VERIFY OFF


VARIABLE g_messageVARCHAR2(100)
DEFINE p_deptno =200
DEFINE p_loc =1400
DECLARE e_invalid_dept EXCEPTION;
v_deptnodepartments.department_id %TYPE :=&p_deptno;
BEGIN
UPDATE departments
SET location_id =&p_loc
WHERE department_id =&p_deptno;
COMMIT;
IF SQL%NOTFOUND THEN
raisee_invalild_dept;
END IF;
EXCEPTION
WHEN e_invalid_dept THEN
:g_message := 'Department'|| TO_CHAR(v_deptno) || 'is an invalid
department';
END;
/
SET VERIFY ON
PRINT g_message
3. Write a PL/SQL block that prints the number of employees who earns
plus or minus $100 of the salary value set for an isql*Plus substitution
variable. Use the DEFINE command to provide the salary. Pass the value
to the PL/SQL block through a isql*Plus substitution variable.
a. If there is no employee within that salary range, print a message to
the user including that is the case. Use exception for this case.
b. If there are one or more employees within that range, the message
should indicate how many employees are in that salary range.
c. Handle any other exception with an appropriate handler. The
message should indicate that some other error occurred.
VARIABLE g_messageVARCHAR2(100)
SET VERIFY OFF
DEFINE p_sal =700
DECLARE
v_salemployees.salary%TYPE :=&p_sal;
v_low_salemployees.salary%TYPE :=&p_sal - 100;
v_high_salemployees.salary%TYPE :=&p_sal + 100;
v_no_emp NUMBER(7);
e_no_emp_returned EXCEPTION;
e_more_than_one_emp EXCEPTION;
BEGIN
SELECT count(last_name)
INTO v_no_emp
FROM employees
WHERE salary between v_low_sal AND v_high_sal;
IF v_no_emp =0 THEN
RAISE e_no_emp_returned;
ELSIF v_no_emp>0 THEN
RAISE e_more_than_one_emp;
END IF;
EXCEPTION
WHEN e_no_emp_returned THEN
:g_message := 'There is no employee salary between'||
TO_CHAR(v_low_sal) || 'and' ||TO_CHAR(v_high_sal);
WHEN e_more_than_one_emp THEN
:g_message:='there is /are ' || TO_CHAR(v_no_emp)||
'employee(s) with a salary between'||
TO_CHAR(v_low_sal) || 'and'||TO_CHAR(v_high_sal);
WHEN others THEN
:g_message:= 'Some other error occurred .';
END;
/
SET VERIFY ON
PRINT g_message
CHAPTER NO : 09
Creatings Procedures
1. Create and invoke the ADD_JOB procedure and consider the result.
a. Create a procedure called ADD_JOBS to insert a new job into the
JOBS table. Provide the ID and title of the job, using two parameters
CREATE OR REPLACE PROCEDURE up_job
(p_job IN jobs.job_id%TYPE, p_jobtitle IN jobs.job_title%TYPE)
IS
BEGIN
UPDATE jobs
SET job_title = p_jobtitle
WHERE job_id= p_jobid;
IF SQL%NOTFOUND THEN
RAISE_APPLICATION_ERROR(-20202,'No job updated.');
END IF;
END upd_job;
b. Compile the code, and invoke the procedure with IT_DBA as job ID
and Database Administrator as job title Query the JOBS table to view
the result.
EXECUTE upd_job(' IT_DBA', 'Data Administrator')
SELECT 8 FROM jobs WHERE job_id = 'IT_DBA';
c. Invoke your procedure again, passing a job ID of ST_MAN and a job
title of Stock Manager. What happens and WHhy?
EXECUTE add_job (‘ST_MAN’,’Stock Manager’)
There is a primary key integrity constraint on the JOB_ID column.
2. Create a procedure called UPD_JOB to modify a job in the JOBS table.
a. Create a procedure called UPD_JOB to update the job title. Provide
the job ID and a new title, using two parameters, include the
necessary exception handling if no update occurs.
CREATE OR REPLACE PROCEDURE upd_job
(p_jobid IN jobs.job_id%TYPE, p_jobtitle IN jobs.job_title%TYPE)
IS
BEGIN
UPDATE jobs
SET job_title= p_jobtitle
WHERE job_id=p_jobid;
IF SQL%NOTFOUND THEN
RAISE_APPLICATION_ERROR(-20202,’No job updated’);
END IF;
END upd_job;
b. Compile the code, and invoke the procedure with IT_DBA as job ID
and Database Administrator as job title Query the JOBS table to view
the result.
EXECUTE upd_job(' IT_DBA', 'Data Administrator')
SELECT 8 FROM jobs WHERE job_id = 'IT_DBA';
Also, check the exception handling by trying to delete a job that does
not exist (use job ID IT_WEB). You should get the message you used
in the exception-handling section of the procedure as output.
EXECUTE upd_job(‘IT_WEB’,’WEB MASTER’)
3. Create a procedure called DEL_JOB to delete a job from the JOBS table.
a. Create a procedure called DEL_JOB to delete a job from JOBS table,
include the necessary exception handling if no job is deleted.
CREATE OR REPLACE PROCEDURE upd_job
(p_jobid IN jobs.job_id%TYPE)
IS
BEGIN
DELETE FROM jobs
WHERE job_id= p_jobid;
IF SQL%NOTFOUND THEN
RAISE_APPLICATION_ERROR(-20202,’No job Deleted’);
END IF;
END upd_job;
b. Compile the code; invoke the procedure using job ID IT_DBA. Query
the JOBS table to view the results.
EXECUTE del_job(‘IT_DBA’)
SELEC T* FROM jobs WHERE job_id=’IT_DBA’;
Also, check the exception handling by trying to delete a job that does
not exist (use job ID IT_WEB). You should get the message you used
in the exception-handling section of the procedure as output.
EXECUTE del_job(‘IT_WEB’)
4. Create a procedure called QUERY_EMP to query the EMPLOYEES table,
retrieving the salary and job ID for an employee when provided with the
employee number.
a. Create a procedure that returns a value from the SALARY and JOB_ID
columns for a specified employee ID.
Use host variable for the two OUT parameters salary and job ID.
CREATE OR REPLACE PROCEDURE query_emp
(p_empid IN employees.employee_id%TYPE,
p_sal OUT employees.salary%TYPE ,
p_job OUT employees.job_id%TYPE)
IS
BEGIN
SELECT salary ,job_id
INTO p_sal, p_job
FROM employees
WHERE employee_id=p_empid;
END query_emp;
b. Complie the code, invoke the procedure to display the salary and job
ID for employee ID 120.
VARIABLE g_sal NUMBER
VARIABLE g_jobVARCHAR2(15)
EXECUTE query_emp (120,:g_sal,:g_job)
PRINT g_sal
PRINT g_job
c. Invoke the procedure again, passing an EMPLOYEE_ID of 300. What
happens and why?
EXECUTE query_emp(300,:g_sal,:g_job)
There is no employee in the EMPLOYEES table with an
EMPLOYEE_ID of 300. The SELECT statement retrieved no data from
the database, resulting in a final PL/SQL error, NO_DATA_FOUND.
CHAPTETR NO:10
CREATING FUNCTIONS

1. Create and invoke the Q_JOB function to return a job title.


a. Create a function called Q-JOB to return a job title to a host variable.
CREATE OR REPLACE FUNCTION q_job
(p_jobid IN jobs.jobs_id%TYPE)
RETURN VARCHAR2
IS
v_jobtitlejob.job_title%TYPE;

BEGIN
SELECT job_title
INTO v_jobtitle
FROM jobs
WHERE job_id =p_jobid;
RETURN (v_jobtitle);
END q_job;
b. Compile the code; create a host variable G_TITLE and invoke the
function with job SA_REP. Query the host variable to view the result.
VARIABLE g_titleVARCHAR2(30)
EXECUTE :g_title :=q_job(‘SA_REP’)
PRINT g_title
2. Create a function called ANNUAL_COMP to return the annual salary by
accepting two parameters: an employee’s monthly salary and
commission. The function should address NULL values.
a. Create a invoke the function the function ANNUAL_COMP, passing in
values for monthly salary and commission. Either or both values
passed can be NULL, but the function should still return an annual
salary, which is not NULL. The annual salary is defined by the basic
formula
(sal*12)+(commission_pct*salary*12)

CREATE OR REPLACE FUNCTION annual_comp


(p_sal INemployees.salary%TYPE,
p_comm IN employees.commission_pct%TYPE)
RETURN NUMBER
IS
BEGIN
RETURN (NVL (p_sal,0)*12+(NVL(p_comm,0)*p_sal*12));
END annual_comp;
/
b. Use the function in a SELECT against the EMPLOYEES table for
department 80.
SELECT employee_id,last_name,
Annual_comp(salary,commission_pct) “Annual Compensation”
FROM employees
WHERE department_id=80;
3. Create a procedure, NEW_EMP, to insert a new employee into the
EMPLOYEES table. The procedure should contain a call to the
VALID_DEPTID function to check whether the department ID specified
for the new employee exists in the DEPARTMENTS table.
a. Create a function VALID_DEPTID to validate a specified department
ID. The function should return a BOOLEAN value.
CREATE OR REPLACE FUNCTION valid_deptid
(p_deptid IN departmetns.depatment_id%TYPE)
RETURN BOOLEAn
IS
v_dummy VARCHAR2(1);
BEGIN
SELECT 'X'
INTO v_dummy
FROM departments
WHERE department_id = p_deptid;
RETURN (TRUE);
EXCEPTION
WHEN NO_DATA_FOUND THEN
RETURN (FALSE);
END valid_deptid;
/
b. Create the procedure NEW_EMP to add an employee to the
EMPLOYEES table. A new row should be added to EMPLOYEES if the
function returns TRUE. If the function returns FALSE, the procedure
should alert the user with an appropriate message.
Defien DEFAUL values for most parameters. The default commission
is 0, the default salary is 1000, the defaualt department ID is 30, the
default job is SA_REP and the default manager number is 145 for the
employee’s ID number, use the sequence EMPLOYEE_SEQ.
Provide the last name, first name and e-mail for the employee.
CREATE OR REPLACE PROCEDURE new_emp
(p_lnameemployees.last_name%TYPE,
p_fnameemployees.first_name%TYPE,
p_emailemployees.email%TYPE,
p_jobemployees.job_id%TYPE DEFAULT ' SA_REP',
p_mgremployees.manager_id%TYPE DEFAULT 145,
p_salemployees.salary%TYPE DEFAULT 1000,
p_commemployees.commission_pct%TYPE DEFAULT 0,
p_depidemployees.department_id%TYPE DEFAULT 30)
IS
IF valid_deptid(p_depid) THEN
INSERT INTO employees
(employee_id,last_name,first_name,email,job_id,manager_id,hire_
date,salary,commission_pct,depatment_id)
VALUES(employees_seq.NEXTVAL,p_lname,p_fname,p_email,p_job
,p_mgr,TRUNC(SYSDATE,'DD'),p_sal,p_comm,p_deptid);
ELSE
RAISE_APPLICATION_ERROR(-20202,'Invalid department ID try
again');
END IF;
END new_emp;
/
c. Test your NEW_EMP procedure by adding a new employee named
Jane Harris to department 15. Allow all other parameters to default.
What was the result?
EXECUTE new_emp (p_lname=>’ Harris‘, p_fname=>’Jane’
p_email=>’HAHARRIS’,p_deptid=15)
d. Test your NEW_EMP procedure by adding an new employee named
Joe Harris to department 80. All other parametes to default. What
was the result?
EXECUTE new_emp (p_lname=>’ Harris‘, p_fname=>’Jane’
p_email=>’HAHARRIS’,p_deptid=80)
CHAPTER NO: 12

1. Create a package specification and body called JOB_PACK. (you can save
the package body and specification in two separate files.) this package
contain your ADD_JOB,UPD_JOB, and DEL_JOB procedures, as well as
your Q_JOB function.
NOTE: Use the code in your previously saved script files when creating the
package.
a. Make all the constructs public.
NOTE: consider whether you still need the stand-alone procedures and
functions you just packaged.
CREATE OR REPLACE PACKAGE job_pack IS
PROCEDURE add_job
(p_jobid IN jobs.job_id%TYPE,
P_jobtitle IN jobs.job_title%TYPE);
PROCEDURE upd_job
(p_jobid IN jobs.job_id%TYPE,
P_jobtitle IN jobs.jobtitle%TYPE);
PROCEDURE del_job
(p_jobid IN jobs.job_id%TYPE);
FUNCTION q_job
(p_jobid IN jobs.job_id%TYPE)
RETURN VARCHAR2;
END job_pack;
/

CREATE OR REPLACE PACKAGE BODY job_pacl IS


PROCEDURE add_job
(p_jobid INjobs.job_id%TYPE,
p_jobtitle IN jobs.job_title%TYPE)
IS
BEGIN
INSERT INTO jobs (job_id, job_title)
VALUES(p_jbid,p_jobtitle);
END add_job;
PROCEDURE upd_job;
(p_jobid IN jobs.job_id%TYPE,
p_jobtitle IN jobs.job_title%TYPE)
IS
BEGIN
UPDATE jobs
SET job_title = p_jobtitle
WHERE job_id =p_jobid;
IF SQL%NOTFOUND THEN
RAISE_APPLICATION_ERROR(-20202,’No job updated’);
END IF;
END upd_job;
PROCEDURE del_job
(p_jobid IN jobs.job_id%TYPE)
IS
BEGIN
DELETE FROM jobs
WHERE job_id=p_jobid;
IF SQL%NOTFOUND THEN
RAISE_APPLICATION_ERROR(-20202,’No job deleted ’);
END IF;
END del_job;
FUNCTION q_job
(p_jobid IN jobs.job_id%TYPE)
RETURN VARCHAR2
IS
V_jobtitlejobs.job_title%TYPE;
BEGIN
SELECT job_title
INTO v_jobtitle
FROM jobs
WHERE job_id=p_jobid;
RETURN (v_jobtitle);
END q_job;
END job_pack;
/
b. Invoke your ADD_JOB procedure by passing values IT_SYSAN and
SYSTEMS ANALYSIS as parameters.
EXECUTE job_pack.add_job(‘IT_SYSAN’,’System Analyst’)
c. Query the JOBS table to see the result.
SELECT * FROM jobs
WHERE job_id=’IT_SYSAN’;

2. Create and invoke a package that contain private can public constructs.
a. Create a package specification and package body called EMP_PACK
that contains your NEW_EMP procedure as a public constructs and
your VALID_DEPTID function as a private construst.
CREATE OR REPLACE PACKAGE emp_pack IS
(p_lnameemployees.last_name%TYPE,
p_fnameemployees.first_name%TYPE,
p_emailemployees.email%TYPE,
p_jobemployees.job_id%TYPE DEFAULT ' SA_REP',
p_mgremployees.manager_id%TYPE DEFAULT 145,
p_salemployees.salary%TYPE DEFAULT 1000,
p_commemployees.commission_pct%TYPE DEFAULT 0,
p_depidemployees.department_id%TYPE DEFAULT 80)
END emp_pack’
/

CREATE OR REPLACE PACKAGE BODY emp_pack IS FUNCTION valid_deptid


(p_deptid IN departmetns.depatment_id%TYPE)
RETURN BOOLEAn
IS
v_dummy VARCHAR2(1);
BEGIN
SELECT 'X'
INTO v_dummy
FROM departments
WHERE department_id = p_deptid;
RETURN (TRUE);
EXCEPTION
WHEN NO_DATA_FOUND THEN
RETURN (FALSE);
END valid_deptid;
PROCEDURE new_emp
(p_lnameemployees.last_name%TYPE,
p_fnameemployees.first_name%TYPE,
p_emailemployees.email%TYPE,
p_jobemployees.job_id%TYPE DEFAULT ' SA_REP',
p_mgremployees.manager_id%TYPE DEFAULT 145,
p_salemployees.salary%TYPE DEFAULT 1000,
p_commemployees.commission_pct%TYPE DEFAULT 0,
p_depidemployees.department_id%TYPE DEFAULT 80)
IS
BEGIN
IF valid_deptid(p_deptid) THEN
INSERT INTO employees
(employee_id,last_name,first_name,email,job_id,manager_id,hire_
date,salary,commission_pct,depatment_id)
VALUES(employees_seq.NEXTVAL,p_lname,p_fname,p_email,p_job
,p_mgr,TRUNC(SYSDATE,'DD'),p_sal,p_comm,p_deptid);
ELSE
RAISE_APPLICATION_ERROR(-20202,'Invalid department ID try
again');
END IF;
END new_emp;
END emp_pack;
/
b. Invoke NEW_EMP procedure, using 15 as a department number. As
the department ID 15 does not exist in the DEPARTMENTS table, you
should get an error message as specified in the exception handler of
your procedure.
EXECUTEemp_pack.new_emp (p_lname=>’ Harris‘, p_fname=>’Jane’
p_email=>’HAHARRIS’,p_deptid=15)
c. Invoke the NEW_EMP procedure using an existing department ID 80;
d. EXECUTE new_emp (p_lname=>’ Smith‘,
p_fname=>’David’p_email=>’DASMITH’,p_deptid=80)

3. a. create a package called CHK_PACK that contain the procedures


CHK_HIREDATE and CHK_DEPT_MGR. make both constructs public.

You might also like