Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Практика. Часть 1.doc
Скачиваний:
0
Добавлен:
01.05.2025
Размер:
238.08 Кб
Скачать

Лабораторная работа № 7.

1. Напишите PL\SQL блок для определения n самых высоких зарплат сотрудников.

a. Выполните скрипт lab_07_01.sql для создания новой таблицы top_salaries,

предназначенную для хранения зарплаты сотрудников.

b. Запросите у пользователя значение переменной n. Пользователи могут

захотеть увидеть зарплату 5, 10 и так далее сотрудников. С помощью

инструкции DEFINE заранее определите переменную p_num для хранения

значения n.

c. Декларируйте переменную num типа NUMBER для хранения значения

p_num, переменную sal типа employees.salary, курсор emp_cursor, который

выбирает зарплату сотрудников в порядке убывания. Помните, что

повторов значений быть не должно.

d. В исполняемой секции кода откройте цикл и выберите первые n записей из

курсора и добавьте их в таблицу top_salaries. Не забывайте про атрибуты

%ROWCOUNT и %FOUND.

e. После добавления значений в таблицу просмотрите их с помощью

инструкции SELECT. Пример результата:

SET SERVEROUTPUT ON;

DEFINE p_num=&n

DECLARE

num NUMBER(3):=&p_num;

sal employees.salary%type;

CURSOR emp_cursor IS SELECT DISTINCT(salary) FROM employee_details ORDER BY salary DESC;

BEGIN

DELETE top_salaries;

DBMS_OUTPUT.ENABLE();

OPEN emp_cursor;

FOR i IN 1..num LOOP

FETCH emp_cursor INTO sal;

IF emp_cursor%found THEN

INSERT INTO top_salaries (salary) VALUES (sal);

ELSE

DBMS_OUTPUT.PUT_LINE('Only ' || i || ' top salaries found');

num:=i;

EXIT;

END IF;

END LOOP;

DBMS_OUTPUT.PUT_LINE(num || ' rows inserted into top_salaries table');

END;

/

f. Протестируйте работу скрипта на различных значениях n: 0, 5, 10, 100,

1000. Не забывайте очищать таблицу top_salaries после каждого теста.

Пример работы кода при любом n>=59

anonymous block completed

Only 59 top salaries found

59 rows inserted into top_salaries table

2. Создайте PL\SQL блок, который делает следующее:

a. С помощью директивы DEFINE определите переменную p_deptno для

хранения department_id значения.

b. Декларируйте переменную deptno типа NUMBER и присвойте ей значение

p_deptno.

c. Декларируйте курсор emp_cursor для выборки last_name, salary и

manager_id сотрудников, работающих в отделе с указанным значением

deptno.

d. В исполняемой секции с помощью инструкции FOR и цикла пройдитесь по курсору и если salary меньше 5000 и manager_id 101 или 124 отобразите сообщение “<<last_name>> Due for a raise.” иначе покажите сообщение “<<last_name>> Not due for a raise.”.

SET SERVEROUTPUT ON;

DEFINE p_deptno NUMBER

DECLARE

deptno NUMBER(3):=&p_deptno;

CURSOR emp_cursor IS SELECT last_name, salary, manager_id

FROM employee_details WHERE department_id = deptno;

BEGIN

DBMS_OUTPUT.ENABLE();

FOR cur IN emp_cursor LOOP

IF cur.salary<5000 AND cur.manager_id IN (101,124) THEN

DBMS_OUTPUT.PUT_LINE(cur.last_name || ' Due for a rase');

ELSE

DBMS_OUTPUT.PUT_LINE(cur.last_name || ' Not due for a rase');

END IF;

END LOOP;

END;

e. Примерный результат:

anonymous block completed

Greenberg Not due for a rase

Faviet Not due for a rase

Chen Not due for a rase

Sciarra Not due for a rase

Urman Not due for a rase

Popp Not due for a rase

3. Напишите PL\SQL для работы с параметризованным курсором.

a. Декларируйте курсор dept_cursor для извлечения department_id, department_name для отделов с номером меньше 100. Отсортируйте выборку по возрастанию номеров отделов.

b. Декларируйте другой курсор emp_cursor, который принимает deptartment_id на вход в качестве параметра и извлекает last_name, job_id, hire_date и salary для тех сотрудников, у которых employee_id меньше 120 и работающих в соответствующем отделе.

c. Декларируйте переменные, для хранения значений, извлеченных из

каждого курсора. Воспользуйтесь директивой %TYPE.

d. Откройте dept_cursor и с помощью простого цикла и инструкции fetch

выберите значения в соответствующую переменную. Распечатайте имя и

номер отдела.

e. Для каждого отдела отройте emp_cursor. С помощью вложенного цикла

пробегитесь по нему, и извлеките значения в соответствующую

переменную и распечатайте их.

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 (p_dept_no departments.department_id%type) IS SELECT last_name, job_id, hire_date, salary FROM employee_details WHERE employee_id<120 AND department_id = p_dept_no;

dept_no departments.department_id%type;

dept_name departments.department_name%type;

e_last_name employee_details.last_name%type;

e_job_id employee_details.job_id%type;

e_hire_date employee_details.hire_date%type;

e_salary employee_details.salary%type;

BEGIN

DBMS_OUTPUT.ENABLE();

OPEN dept_cursor;

LOOP

FETCH dept_cursor INTO dept_no, dept_name;

IF dept_cursor%found THEN

DBMS_OUTPUT.PUT_LINE(dept_no||' '||dept_name);

OPEN emp_cursor (dept_no);

LOOP

FETCH emp_cursor INTO e_last_name,e_job_id,e_hire_date,e_salary;

IF emp_cursor%notfound THEN

CLOSE emp_cursor;

EXIT;

ELSE

DBMS_OUTPUT.PUT_LINE(e_last_name || ' ' || e_job_id || ' ' || e_hire_date || ' ' || e_salary);

END IF;

END LOOP;

ELSE

CLOSE dept_cursor

EXIT;

END IF;

END LOOP;

END;

f. Закрой все циклы и курсоры в правильной последовательности. Выполните

скрипт. Результат должен быть похож на рисунок:

anonymous block completed

10 Administration

20 Marketing

30 Purchasing

Raphaely PU_MAN 07-DEC-02 11000

Khoo PU_CLERK 18-MAY-03 3100

Baida PU_CLERK 24-DEC-05 2900

Tobias PU_CLERK 24-JUL-05 2800

Himuro PU_CLERK 15-NOV-06 2600

Colmenares PU_CLERK 10-AUG-07 2500

40 Human Resources

50 Shipping

60 IT

Hunold IT_PROG 03-JAN-06 9000

Ernst IT_PROG 21-MAY-07 6000

Austin IT_PROG 25-JUN-05 4800

Pataballa IT_PROG 05-FEB-06 4800

Lorentz IT_PROG 07-FEB-07 4200

70 Public Relations

80 Sales

90 Executive

King AD_PRES 17-JUN-03 24000

Kochhar AD_VP 21-SEP-05 17000

De Haan AD_VP 13-JAN-01 17000

4. Загрузите скрипт lab_06_04_soln.sql.

a. Найдите инструкцию: “DECLARE A CURSOR CALLED emp_records TO

HOLD salary, first_name, and last_name of employees” и создайте декларацию

курсора emp_records с соответствующей структурой. Курсор FOR UPDATE

должен выбирать salary, first_name и last_name сотрудников определенного

отдела (WHERE department_id=emp_deptid).

b. Начните с помощью инструкции BEGIN исполняемую секцию в

соответствии с комментарием: “INCLUDE EXECUTABLE SECTION OF

INNER BLOCK HERE”.

c. Основной код во вложенном блоке должен выполняться только в том

случае, если emp_deptid содержит номера 20,60,80,100,110 отделов, иначе

сообщите о невозможности продолжения работы с помощью инструкции

DBMS_OUTPUT.PUT_LINE (пример фразы: 'SORRY, NO SALARY

REVISIONS FOR EMPLOYEES IN THIS DEPARTMENT'). Если номер

отдела все в порядке, то необходимо открыть emp_records курсор.

d. С помощью простого цикла и оператора fetch извлеките значения из

курсора в переменные emp_sal,emp_fname,emp_lname. Для завершения

работы цикла воспользуйтесь атрибутом %NOTFOUND.

e. В тело цикла включите инструкцию CASE для анализа значения

переменной emp_sal. Используйте для проверки константы range1, hike1 и

т.д., которые уже декларированы. Правила обработки приведены в таблице:

Пример кода для обработки одного из случаев:

WHEN emp_sal<c_range1 THEN

ename_table(i):=emp_fname||' '||emp_lname;

i:=i+1;

UPDATE employee_details SET salary=emp_sal + (emp_sal*c_hike1)

WHERE CURRENT OF emp_records;

f. Закройте цикл LOOP. С помощью атрибута %ROWCOUNT распечатайте

количество обновленных строк. Закройте курсор.

g. С помощью простого цикла LOOP распечатайте имена сотрудников, анализ

зарплаты которых был произведен. Список имен сохранен в INDEX BY

TABLE. Найдите комментарий: «CLOSE THE INNER BLOCK» и закройте оператор IF и вложенный блок.

SET SERVEROUTPUT ON

SET VERIFY OFF

ACCEPT emp_id PROMPT 'Please enter your employee number';

ACCEPT emp_dept PROMPT 'Please enter the department number for which salary revision is being done';

DECLARE

emp_authorization NUMBER(5);

emp_id NUMBER(5):=&emp_id;

emp_deptid NUMBER(6):=&emp_dept;

no_such_employee EXCEPTION;

v_employee_id employee_details.employee_id%type;

-- INCLUDE EXECUTABLE SECTION OF OUTER BLOCK HERE

BEGIN

-- RAISE EXCEPTION HERE

DBMS_OUTPUT.ENABLE();

-- INCLUDE SIMPLE IF STATEMENT HERE

emp_authorization := emp_id;

IF emp_authorization = emp_id THEN

SELECT employee_id INTO v_employee_id FROM employee_details WHERE department_id IN (SELECT department_id FROM departments WHERE department_name = 'Human Resources');

DECLARE

emp_sal employee_details.salary%TYPE;

emp_fname employee_details.first_name%TYPE;

emp_lname employee_details.last_name%TYPE;

i NUMBER:=1;

-- DECLARE AN INDEX BY TABLE OF TYPE VARCHAR2(50). CALL

-- IT ename_table_type

TYPE ename_table_type IS TABLE OF VARCHAR2(50) INDEX BY BINARY_INTEGER;

ename_table ename_table_type;

-- DECLARE A VARIABLE ename_table OF TYPE ename_table_type

c_hike1 constant real :=.20;

c_hike2 constant real :=.15;

c_hike3 constant real :=.08;

c_hike4 constant real :=.03;

c_range1 constant number :=6500;

c_range2 constant number :=9500;

c_range3 constant number :=12000;

-- DECLARE A CURSOR CALLED emp_records TO HOLD salary,

-- first_name, and last_name of employees

CURSOR emp_records (emp_deptid NUMBER) IS SELECT salary, first_name, last_name FROM employee_details WHERE department_id=emp_deptid FOR UPDATE;

-- INCLUDE EXECUTABLE SECTION OF INNER BLOCK HERE

BEGIN

IF emp_deptid IN (20,60,80,100,110) THEN

DBMS_OUTPUT.PUT_LINE('SORRY, NO SALARY REVISIONS FOR EMPLOYEES IN THIS DEPARTMENT');

ELSE

OPEN emp_records (emp_deptid);

LOOP

FETCH emp_records INTO emp_sal, emp_fname, emp_lname;

IF emp_records%notfound THEN

EXIT;

ELSE

CASE

WHEN emp_sal<c_range1 THEN

ename_table(i):=emp_fname || ' ' || emp_lname;

i:=i+1;

UPDATE employee_details SET salary=emp_sal + (emp_sal*c_hike1) WHERE CURRENT OF emp_records;

WHEN emp_sal<c_range2 THEN

ename_table(i):=emp_fname || ' ' || emp_lname;

i:=i+1;

UPDATE employee_details SET salary=emp_sal + (emp_sal*c_hike2) WHERE CURRENT OF emp_records;

WHEN emp_sal<c_range3 THEN

ename_table(i):=emp_fname || ' ' || emp_lname;

i:=i+1;

UPDATE employee_details SET salary=emp_sal + (emp_sal*c_hike3) WHERE CURRENT OF emp_records;

ELSE

ename_table(i):=emp_fname || ' ' || emp_lname;

i:=i+1;

UPDATE employee_details SET salary=emp_sal + (emp_sal*c_hike4) WHERE CURRENT OF emp_records;

END CASE;

END IF;

END LOOP;

DBMS_OUTPUT.PUT_LINE('Number of records updated: '|| emp_records%rowcount);

CLOSE emp_records;

END IF;

FOR k IN 1..i LOOP

DBMS_OUTPUT.PUT_LINE(ename_table(k));

null;

END LOOP;

-- CLOSE THE INNER BLOCK

END;

ELSE

DBMS_OUTPUT.PUT_LINE ('SORRY YOU ARE NOT AUTHORIZED TO USE THIS APPLICATION');

END IF;

-- INCLUDE EXCEPTION SECTION FOR OUTER BLOCK

EXCEPTION

WHEN OTHERS THEN

DBMS_OUTPUT.PUT_LINE('Exception occured');

-- CLOSE THE OUTER BLOCK

END;

/

h. Сохраните скрипт под именем lab_04_07_soln.sql