You are on page 1of 15

Rakha Haris

TI – 3B

Cursor and Record


1. Exercise using CURRENCIES tables
a. Write a PL/SQL block to declare a cursor called currencies_cur. The cursor will
be used to read and display all rows from the CURRENCIES table. You will need
to retrieve currency_code and currency_name, ordered by ascending
currency_name.
b. Add a statement to open the currencies_cur cursor.
c. Add variable declarations and an executable statement to read ONE row through
the currencies_cur cursor into local variables.
d. Add a statement to display the fetched row, and a statement to close the
currencies_cur cursor.
e. Run your block to check that it works. It should display: AFA Afghani.

DECLARE
CURSOR currencies_cur IS
SELECT currency_code,currency_name FROM currencies ORDER BY
CURRENCY_NAME;
v_curr_code currencies.currency_code%TYPE;
v_curr_name currencies.currency_name%TYPE;
BEGIN
OPEN currencies_cur;
FETCH currencies_cur INTO v_curr_code, v_curr_name;
DBMS_OUTPUT.PUT_LINE(v_curr_code|| ' ' || v_curr_name);
CLOSE currencies_cur;
END;

f. Your code so far displays only one row. Modify your code so that it fetches and
displays all the rows, using a LOOP and EXIT statement. Test your modified
block. It should fetch and display each row in the CURRENCIES table. If it
doesn't, check that your EXIT statement is in the correct place in the code.

DECLARE
CURSOR currencies_cur IS
SELECT currency_code,currency_name FROM currencies ORDER BY
CURRENCY_NAME;
v_curr_code currencies.currency_code%TYPE;
v_curr_name currencies.currency_name%TYPE;
BEGIN
OPEN currencies_cur;
LOOP
FETCH currencies_cur INTO v_curr_code, v_curr_name;
DBMS_OUTPUT.PUT_LINE(v_curr_code|| ' ' || v_curr_name);
EXIT WHEN currencies_cur%NOTFOUND;
END LOOP;
CLOSE currencies_cur;
END;
g. Write and test a PL/SQL block to read and display all the rows in the
COUNTRIES table for all countries in region 5 (South America region). For each
selected country, display the country_name, national_holiday_date, and
national_holiday_name. Display only those countries having a national holiday
date that is not null.
DECLARE
v_c_name countries.country_name%TYPE;
v_h_date countries.national_holiday_date%TYPE;
v_h_name countries.national_holiday_name%TYPE;
CURSOR countries_cur IS
SELECT country_name, national_holiday_date, national_holiday_name
FROM countries WHERE region_id = 5 AND national_holiday_date IS NOT NULL;
BEGIN
OPEN countries_cur;
LOOP
FETCH countries_cur INTO v_c_name, v_h_date, v_h_name;
EXIT WHEN countries_cur%NOTFOUND;
DBMS_OUTPUT.PUT_LINE('country: ' || v_c_name ||
' National Holiday: ' || v_h_name || ' Held on: ' || v_h_date);
END LOOP
CLOSE;
END;

2. Write a PL/SQL block to read through rows in the countries table for all countries in region 5
(South America region). For each selected country, display the country_name,
national_holiday_date, and national_holiday_name. Use a record structure to hold all the
columns selected from the countries table.
SET SERVEROUTPUT ON;
DECLARE
CURSOR countries_cur IS
SELECT country_name, national_holiday_name, national_holiday_date
FROM countries WHERE region_id = 5;
countries_rec countries_cur%ROWTYPE;
BEGIN
OPEN countries_cur;
LOOP
FETCH countries_cur INTO countries_rec;
EXIT WHEN countries_cur%NOTFOUND;
DBMS_OUTPUT.PUT_LINE('Country : '||countries_rec.country_name||', National
Holiday :
'||countries_rec.national_holiday_name||
', held on : '||countries_rec.national_holiday_date);
END LOOP;
CLOSE countries_cur;
END;
3. Use the employees table. Create a PL/SQL block that fetches and displays the six employees
with the highest salary. For each of these employees, display the first name, last name, job id,
and salary. Order your output so that the employee with the highest salary is displayed first. Use
%ROWTYPE and the explicit cursor attribute %ROWCOUNT.

SET SERVEROUTPUT ON;


DECLARE
CURSOR emp_cursor IS
SELECT first_name, last_name, job_id, salary
FROM employees
ORDER BY salary DESC;
emp_record emp_cursor%ROWTYPE;
BEGIN
OPEN emp_cursor;
LOOP
FETCH emp_cursor INTO emp_record;
EXIT WHEN emp_cursor%ROWCOUNT > 6;
DBMS_OUTPUT.PUT_LINE(emp_record.first_name||' '||emp_record.last_name||' '||
emp_record.job_id||' '||emp_record.salary);
END LOOP;
CLOSE emp_cursor;
END;
4. Modify the following PL/SQL block so that it uses a cursor FOR loop. Keep the explicit
cursor declaration in the DECLARE section. Test your changes.
DECLARE
CURSOR countries_cur IS
SELECT country_name, national_holiday_name, national_holiday_date
FROM countries
WHERE region_id = 5;
countries_rec countries_cur%ROWTYPE;
BEGIN
OPEN countries_cur;
LOOP
FETCH countries_cur INTO countries_rec;
EXIT WHEN countries_cur%NOTFOUND;
DBMS_OUTPUT.PUT_LINE ('Country: ' || countries_rec.country_name || ' National
holiday: '||
countries_rec.national_holiday_name
|| ', held on: '|| countries_rec.national_holiday_date);
END LOOP;
CLOSE countries_cur;
END;

SET SERVEROUTPUT ON;


DECLARE
CURSOR countries_cur IS
SELECT country_name, national_holiday_name, national_holiday_date
FROM countries WHERE region_id = 5;
BEGIN
FOR countries_rec IN countries_cur
LOOP
DBMS_OUTPUT.PUT_LINE ('Country: ' || countries_rec.country_name || ' National
holiday: '||
countries_rec.national_holiday_name
|| ', held on: '|| countries_rec.national_holiday_date);
END LOOP;
END;
5. Using the COUNTRIES table, write a cursor that returns countries with a highest_elevation
greater than 8,000 m. For each country, display the country_name, highest_elevation, and
climate. Use a cursor FOR loop, declaring the cursor using a subquery in the FOR…LOOP
statement.

SET SERVEROUTPUT ON;

BEGIN
FOR countries_rec IN
(SELECT country_name, highest_elevation, climate
FROM countries
WHERE highest_elevation > 8000)
LOOP
DBMS_OUTPUT.PUT_LINE('Country name: '|| countries_rec.country_name ||'the
highest elevation is:
'||
countries_rec.highest_elevation||' and the climate is: '||countries_rec.climate);
END LOOP;
END;
Procedure and Function
1. What is the difference between the following two pieces of code?

 Code Sample A merupakan anonymous block, sedangkan Code Sample B merupakan


procedure
 Code Sample A tidak disimpan di database, sedangkan Code Sample B disimpan di
database
 Code Sample A tidak ada IS, sedangkan Code Sample B ada IS
 Code Sample A ada DECLARE, sedangkan Code Sample B tidak perlu karna sudah ada
CREATE PROCEDURE

2. Create the copy by executing the following SQL statement:


CREATE TABLE employees_dup AS SELECT * from employees;
3. Use the code below to create a procedure in Application Express. Save the definition of your
procedure in case you need to modify it later. In the “Save SQL” popup, name your saved work
“My name change procedure.”
CREATE OR REPLACE PROCEDURE name_change IS
BEGIN
UPDATE employees_dup
SET first_name = 'Susan'
WHERE department_id = 80;
END name_change;
4. Execute the procedure by running the following anonymous block:
BEGIN
name_change;
END;
5. Create a second procedure named pay_raise which changes the salary of all employees in
employees_dup to a new value of 30000. Execute the procedure from an anonymous block, then
SELECT from the table to check that the procedure has executed correctly

SET SERVEROUTPUT ON;


CREATE OR REPLACE PROCEDURE pay_raise IS
BEGIN
UPDATE employees_dup
SET salary = 30000;
END pay_raise;

BEGIN
pay_raise;
END;
6. Create, save, and execute a procedure which updates the salary of employees in
employees_dup according to the following rules:
- if the employee is in department 80, the new salary = 1000
- if the employee is in department 50, the new salary = 2000
- if the employee is in any other department, the new salary = 3000.
You will need to include three UPDATE statements, one for each of the above rules. In a later
lesson you will learn how to avoid this. Execute your procedure from an anonymous block and
verify that the updates have been performed correctly.

SET SERVEROUTPUT ON;


CREATE OR REPLACE PROCEDURE salaryChange IS
BEGIN
UPDATE employees_dup
SET salary = 1000
WHERE department_id = 80;
UPDATE employees_dup
SET salary = 2000
WHERE department_id = 50;
UPDATE employees_dup
SET salary = 3000
WHERE department_id NOT IN (80, 50);
END salaryChange;

BEGIN
salaryChange;
END;
7. Using the COUNTRIES table:
a. Create a procedure that accepts a country_id as a parameter and displays the name of
the country and its capitol city. Name your procedure get_country_info. Save your
procedure definition for later use.

SET SERVEROUTPUT ON;


CREATE OR REPLACE PROCEDURE get_country_info
(p_country_id IN countries.country_id%TYPE)
IS
v_country_name countries.country_name%TYPE;
v_capitol countries.capitol%TYPE;
BEGIN
SELECT country_name, capitol INTO v_country_name, v_capitol
FROM countries
WHERE country_id = p_country_id;
DBMS_OUTPUT.PUT_LINE('The country name is '||v_country_name||'and the capital
city is '|| v_capitol);
END;
b. Execute your procedure from an anonymous block, using country_id 90
BEGIN
get_country_info(90);
END;
c. Retrieve your procedure code from Saved SQL and modify it to trap the
NO_DATA_FOUND exception in an exception handler.

SET SERVEROUTPUT ON;


CREATE OR REPLACE PROCEDURE get_country_info
(p_country_id IN countries.country_id%TYPE)
IS
v_country_name countries.country_name%TYPE;
v_capitol countries.capitol%TYPE;
BEGIN
SELECT country_name, capitol INTO v_country_name, v_capitol
FROM countries
WHERE country_id = p_country_id;
DBMS_OUTPUT.PUT_LINE('The country name is '||v_country_name||'and the capital
city is '|| v_capitol);
EXCEPTION
WHEN NO_DATA_FOUND THEN
DBMS_OUTPUT.PUT_LINE('No data found for COUNTRY_ID=' || p_country_id);
END;

8. Create a function called full_name. Pass two parameters to the function, an employee’s last
name and first name. The function should return the full name in the format, last name, comma,
space, first name (for example: Smith, Joe).
SET SERVEROUTPUT ON;
CREATE OR REPLACE FUNCTION full_name
(p_last_name employees.last_name%TYPE, p_first_name employees.first_name%TYPE)
RETURN VARCHAR2
IS
BEGIN
RETURN (p_last_name||', '||p_first_name);
END;
9. Test your function from an anonymous block which uses a local variable to store and display
the returned value.

DECLARE
v_full_name VARCHAR2(50);
BEGIN
v_full_name := full_name('Smith','Joe');
DBMS_OUTPUT.PUT_LINE('The name is: '|| v_full_name);
END;
10. Create a function called divide that accepts two numbers as input and returns the result of
dividing the first number by the second number, rounded to two decimal places. Save your code.
SET SERVEROUTPUT ON;
CREATE OR REPLACE FUNCTION divide(n1 NUMBER, n2 NUMBER)
RETURN NUMBER IS
rez NUMBER;
BEGIN
rez:=ROUND(n1/n2, 2);
RETURN rez;
END;
11. Test your function twice from an anonymous block using input values (50, 2) and (25, 3).

DECLARE
v_test NUMBER;
BEGIN
v_test:=divide(50,2);
DBMS_OUTPUT.PUT_LINE(v_test);
END;
DECLARE
v_test NUMBER;
BEGIN
v_test:=divide(25,3);
DBMS_OUTPUT.PUT_LINE(v_test);
END;

You might also like