Отправляет email-рассылки с помощью сервиса Sendsay

Килограмм килобайтов

  Все выпуски  

Килограмм килобайтов


"Килограмм килобайтов"


Выпуск №44 Дата выхода:2008-12-23
Сайт рассылки: Рациональное программирование

Документация
 
Программирование
Java
PHP
Oracle
Операционные системы
FreeBSD
Linux
QNX
Windows

Здравствуйте, уважаемые подписчики

Завершаю публикацию статьи об использовании выражения BULK COLLECT в Oracle.
Третья часть.

Ограничение числа рядов в выборке с помощью условия Limit

Дополнительное условие LIMIT может использоваться только с выражением FETCH и ограничивает число рядов, выбираемых из баз данных. В следующем примере на каждой итерации цикла извлекается не больше десяти рядов и помещается в таблицу empids. Предыдущие значения перетираются. Обратите внимание на использование empids.count как условия выхода из цикла.

Пример



DECLARE
  TYPE numtab IS TABLE OF NUMBER INDEX BY PLS_INTEGER;
  CURSOR c1 IS 
    SELECT employee_id 
         FROM employees 
       WHERE department_id = 80;

  empids numtab;
  rows PLS_INTEGER := 10;
BEGIN
  OPEN c1;
  LOOP -- следующее выражение извлекает не больше 10 рядов за одну итерацию
    FETCH c1 BULK COLLECT INTO empids LIMIT rows;
    EXIT WHEN empids.COUNT = 0;
    -- EXIT WHEN c1%NOTFOUND; -- это условие некорректно, можно потерять часть данных
  DBMS_OUTPUT.PUT_LINE('------- Results from Each Bulk Fetch --------');
    FOR i IN 1..empids.COUNT 
    LOOP
      DBMS_OUTPUT.PUT_LINE( 'Employee Id: ' || empids(i));
    END LOOP;
  END LOOP;
  CLOSE c1;
END;
/

Передача результатов операций DML в коллекцию, используя выражение RETURNING INTO

Вы можете использовать BULK COLLECT в условии RETURNING INTO выражений INSERT, UPDATE, DELETE.

Пример



CREATE TABLE emp_temp AS SELECT * FROM employees;

DECLARE
  TYPE NumList IS TABLE OF employees.employee_id%TYPE;
  enums NumList;
  TYPE NameList IS TABLE OF employees.last_name%TYPE;
  names NameList;
BEGIN
  DELETE FROM emp_temp WHERE department_id = 30
  RETURNING employee_id, last_name BULK COLLECT INTO enums, names;
  DBMS_OUTPUT.PUT_LINE('Deleted ' || SQL%ROWCOUNT || ' rows:');
  FOR i IN enums.FIRST..enums.LAST
  LOOP
    DBMS_OUTPUT.PUT_LINE('Employee #' || enums(i) || ': ' || names(i));
  END LOOP;
END;
/

Совместное использование FORALL и BULK COLLECT

Вы можете объединить условие BULK COLLECT и выражение FORALL. Результирующая коллекция будет заполнена итерациями выражения FORALL. В следующем примере для каждого удаленного ряда значение employee_id сохраняется в коллекцию e_ids. Коллекция depts хранит три элемента, таким образом выражение FORALL выполнит три итерации. Если каждый оператор DELTE выполненный выражением FORALL удалит пять рядов, то в результате коллекция e_ids, которая хранит значения из удаленных рядов, будет содержать 15 элементов.

Пример

 
CREATE TABLE emp_temp AS SELECT * FROM employees;

DECLARE
  TYPE NumList IS TABLE OF NUMBER;
  depts NumList := NumList(10,20,30);
  TYPE enum_t IS TABLE OF employees.employee_id%TYPE;
  TYPE dept_t IS TABLE OF employees.department_id%TYPE;
  e_ids enum_t;
  d_ids dept_t;
BEGIN
  FORALL j IN depts.FIRST..depts.LAST
    DELETE FROM emp_temp WHERE department_id = depts(j)
         RETURNING employee_id, department_id BULK COLLECT INTO e_ids, d_ids;
    DBMS_OUTPUT.PUT_LINE('Deleted ' || SQL%ROWCOUNT || ' rows:');
  FOR i IN e_ids.FIRST .. e_ids.LAST
  LOOP
    DBMS_OUTPUT.PUT_LINE('Employee #' || e_ids(i) || ' from dept #' || d_ids(i));
  END LOOP;
END;
/

Значения столбцов, удаленных каждой итерацией, добавляются к ранее полученным значениям коллекций. Если бы использовался цикл FOR вместо выражения FORALL, то набор результирующих значений перетирался бы следующим выполнением выражения DELETE. Не допускается использование конструкции SELECT ... BULK COLLECT в выражении FORALL.

Петрелевич Сергей
petrelevich@yandex.ru


* * *

Ведущий рассылки: Петрелевич Сергей

У Вас есть вопрос? Спрашивайте
Напишите, что Вы хотите видеть в рассылке. Мне важно знать Ваше мнение.


В избранное