PLSQL
PLSQL
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;
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.
v_message VARCHAR2(40);
BEGIN
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
BEGIN
DECLARE
BEGIN
v_weight :=v_weight+1;
END;
v_weight :=v_weight+1;
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. 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
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.
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
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.
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
g. Display the rows from the EMP table to verify whether your
PL/SQL block has executed successfully.
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
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.
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
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
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
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)
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;
/
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’
/