
- •Формирование запросов к базе данных.
- •Множественные операции
- •Order by
- •For update of
- •Последовательности
- •Фразы оператора select
- •Фраза from
- •Фразы group by и having
- •Фраза having
- •Фраза where
- •Фраза where (Встроенный sql)
- •Фраза current of
- •Фразы connect by и start with
- •Start with
- •Использование order by
- •Фраза order by
- •Внешнее объединение
- •Подзапросы.
- •Функции агрегирования результатов запроса
- •Курсоры
- •Види курсоров
- •Объявление курсора.
- •Открытие курсора
- •Атрибуты курсора.
- •Чтение данных с использованием курсора.
- •Закрытие курсора
- •Неявные курсоры. Предопределенный курсор sql.
- •Примеры работы с курсорами
- •Изменение и удаление данных в позиции курсора.
- •Переменные-курсоры.
- •Работа с транзакциями в pl/sql.
- •Курсоры и транзакции.
Примеры работы с курсорами
Первый пример иллюстрирует использование курсора с параметрами.
Пусть курсор должен возвращать всех сотрудников данного подразделения.
Мы можем записать его так
DECLARE
CURSOR emp_dcur (dep_name_in VARCHAR2 := 'Accounting') IS
SELECT
emp_id, emp_name, dep_name_in FROM Employee, Department
WHERE Employee.dep_id=Department.dep_id
AND UPPER(Department.dep_name)=UPPER(dep_name_in);
(функция UPPER() используется для того, чтобы допустить запросы в любом регистре) и пользоваться им так:
OPEN emp_dcur('Marketing');
FETCH emp_dcur INTO my_emp_id, my_emp_name, my_dep_name;
CLOSE emp_dcur;
OPEN emp_dcur('Sales'); -- и т.д.
Второй пример иллюстрирует т.н. технику двойного FETCH.
Предположим, нам нужно, чтобы пользователь ввел имя подразделения для конкретного сотрудника (полное или частичное). Если пользователь задал уникальное имя, то нужно показать ему код подразделения. Если запрос вернул несколько подразделений, пользователю нужно сообщить об этом, а если ни одного - отменить весь запрос.
Напрашивается написать запрос, который вернет общее число подразделений с использованием функции COUNT(), а потом принять решение - если он вернул 1, сделать запрос для получения dep_id, иначе - соответственно.
Но это не лучшее решение проблемы. COUNT() неэффективен (особенно с курсорами) и дает нам лишнюю информацию, ведь нам фактически не нужно знать, сколько на самом деле там подразделений, нам нужно знать, одно оно или их много (или нет ни одного). С другой стороны, запрос с COUNT() возвращает недостаточно информации, т.к. для получения dep_id в случае, если запрос вернул одно значение, нужно опять лезть в базу.
Делать нужно так:
1) определить курсор, который возвращает dep_id для всех компаний, которые соответствуют запросу.
DECLARE
CURSOR dep_cur IS SELECT dep_id FROM Department WHERE dep_name
LIKE dep_name_in || '%';
2) дважды сделать FETCHдля этого курсора. Если два раза все в порядке
dep_cur%NOTFOUND FALSE - у нас более одного подразделения.
Если во второй раз TRUE - у нас одно подразделение и мы уже получили dep_id. Иначе - ни одного.
Изменение и удаление данных в позиции курсора.
Помимо чтения данных, с помощью курсора (если он был объявлен с предложением FOR UPDATE) можно также изменять данные. Для этого существуют специальные формы операторов DELETE и UPDATE, называемые позиционными DELETE и UPDATE.
Cинтаксис позиционного DELETE следующий:
DELETE FROM таблица WHERE CURRENT OF имя-курсора
В этом случае будет удалена строка, на которой в данный момент находится курсор, заданный параметром "имя-курсора". Курсор предварительно должен быть установлен в эту позицию оператором FETCH. Если курсор не установлен на конкретную запись, то удаление не произойдет. После удаления курсор установится перед следующей записью набора или сразу же после последней (если была удалена последняя запись).
Пример:
DELETE FROM Employee WHERE CURRENT OF emp_cursor;
Можно посмотреть результаты DELETEс помощью атрибутов курсораSQL:
- при удалении одной или нескольких записей,
SQL%NOTFOUND даст FALSE, SQL%FOUND даст TRUE,
SQL%ROWCOUNTдаст число удаленных записей
- если ничего удалено не было,
SQL%NOTFOUND даст TRUE, SQL%FOUND - FALSE, SQL%ROWCOUNT - 0
Позиционный UPDATE имеет следующий вид:
UPDATE таблица SET поле=значение[,...]
WHERE CURRENT OF имя-курсора
Здесь все, что касается SET, аналогично обычному оператору UPDATE (при этом допустимы переменные связи) и будет изменена строка, на которой находится курсор. С помощью этого оператора нельзя изменять поля, по которым была произведена сортировка запроса, лежащего в основе курсора (т.е, указанные в ORDER BY).
Пример:
UPDATE Employee SET emp_lname='Павлов' WHERE CURRENT OF
emp_cursor;
Просмотреть результаты изменения с помощью SQL% можно аналогично DELETE, только считаются измененные записи.