powered by simpleCommunicator - 2.0.61     © 2026 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / Oracle [игнор отключен] [закрыт для гостей] / Копирование списков порциями
25 сообщений из 29, страница 1 из 2
Копирование списков порциями
    #39730020
ultrasonic7
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Добрый день! В таблице SCHEMA_NAME.TABLE_NAME есть 10000 значений. Нужно их порциями по 100 штук копировать в список, производить какие-то действия с ним и замерять время для каждых 100 значений. Мне представляется такой вариант:

Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
DECLARE
  l_VPUSubList   SYS.ODCINUMBERLIST;
  l_TotalVPUList SYS.ODCINUMBERLIST;
  indSub   INTEGER;   indTotal INTEGER;
  start_time TIMESTAMP WITH TIME ZONE;
  end_time TIMESTAMP WITH TIME ZONE;
  exec_length INTERVAL DAY TO SECOND;
BEGIN
  select VPU_NUM 
  BULK COLLECT INTO l_TotalVPUList
  from SCHEMA_NAME.TABLE_NAME
  
  indSub := 1; indTotal := 1;
  WHILE indTotal <= l_TotalVPUList.LAST
  LOOP
    --dbms_output.put_line (ind);
    l_VPUSubList(indSub) := l_TotalVPUList(indTotal);
    indSub := indSub + 1; indTotal := indTotal + 1;
    IF MOD (indTotal, 100) = 0 -- Каждые 100 значений
    THEN
      start_time := SYSTIMESTAMP;
      --Здесь какие-то действия с этими 100 значений
      end_time := SYSTIMESTAMP;
      exec_length := end_time - start_time;
      dbms_output.put_line('Длина в формате дни часы:минуты:секунды: '||exec_length);
    END IF;
  END LOOP;  
END;



Но при попытке запуска скрипта возниакет ошибка:ORA-06531: Ссылка на неинициализированный набор
ORA-06512: на line 18

Как избавиться от неё или как более эффективно написать скрипт?
...
Рейтинг: 0 / 0
Копирование списков порциями
    #39730023
Фотография andrey_anonymous
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
ultrasonic7Как избавиться от неё или как более эффективно написать скрипт?
1. bulk collect имеет кляузу LIMIT.
2. Изложите цикл в виде
Код: plsql
1.
for i in 1.. l_TotalVPUList.count loop


Это избавит от необходимости отдельно обрабатывать случай пустой коллекции, с которым Вы столкнулись.
...
Рейтинг: 0 / 0
Копирование списков порциями
    #39730025
Вячеслав Любомудров
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Я думаю, что тут столкнулись с
ultrasonic7
Код: plsql
1.
2.
...
    l_VPUSubList(indSub) := l_TotalVPUList(indTotal);
...
Рейтинг: 0 / 0
Копирование списков порциями
    #39730027
Фотография -2-
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
ultrasonic7Как избавиться от неёпоставить return после begin, потому как очевидного решения, инициализировать переменную, будет недостаточно, чтобы избежать последующих ошибок.
ultrasonic7как более эффективно написать скрипт?курсор + limit 100
...
Рейтинг: 0 / 0
Копирование списков порциями
    #39730028
Фотография andrey_anonymous
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
andrey_anonymousслучай пустой коллекции, с которым Вы столкнулись.
Слишком по диагонали смотрел, сорри.
Вот это:
Код: plsql
1.
l_VPUSubList   SYS.ODCINUMBERLIST;


надо инициализировать и расширять руками.
Лучше объявите ассоциативный массив.
...
Рейтинг: 0 / 0
Копирование списков порциями
    #39730029
Фотография SY
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
ultrasonic7Как избавиться

Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
DECLARE
  l_VPUSubList   SYS.ODCINUMBERLIST := SYS.ODCINUMBERLIST();
  l_TotalVPUList SYS.ODCINUMBERLIST;
  indSub   INTEGER;   indTotal INTEGER;
  start_time TIMESTAMP WITH TIME ZONE;
  end_time TIMESTAMP WITH TIME ZONE;
  exec_length INTERVAL DAY TO SECOND;
BEGIN
  select VPU_NUM 
  BULK COLLECT INTO l_TotalVPUList
  from SCHEMA_NAME.TABLE_NAME
  
  indSub := 1; indTotal := 1;
  l_VPUSubList.extend(l_TotalVPUList.LAST);
  WHILE indTotal <= l_TotalVPUList.LAST
  LOOP
    --dbms_output.put_line (ind);
    l_VPUSubList(indSub) := l_TotalVPUList(indTotal);
    indSub := indSub + 1; indTotal := indTotal + 1;
    IF MOD (indTotal, 100) = 0 -- Каждые 100 значений
    THEN
      start_time := SYSTIMESTAMP;
      --Здесь какие-то действия с этими 100 значений
      end_time := SYSTIMESTAMP;
      exec_length := end_time - start_time;
      dbms_output.put_line('Длина в формате дни часы:минуты:секунды: '||exec_length);
    END IF;
  END LOOP;  
END;



SY
...
Рейтинг: 0 / 0
Копирование списков порциями
    #39730333
ultrasonic7
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Суть в том, что l_VPUSubList должен быть именно типа SYS.ODCINUMBERLIST и содержать 100 элементов.
То, что список надо расширить
Код: plsql
1.
l_VPUSubList.extend(l_TotalVPUList.LAST);


понятно. Но l_TotalVPUList.LAST содержит 10000 значений, а мне нужно копировать в l_VPUSubList порциями по 100 и для каждой итерации цикла вызывать процедуру, у которой входной параметр SYS.ODCINUMBERLIST и условия запуска требуют, чтобы в нём было 100 значений.
Не проще ли будет один раз расширить l_VPUSubList на 100 элементов?
Код: plsql
1.
l_VPUSubList.extend(100);
...
Рейтинг: 0 / 0
Копирование списков порциями
    #39730344
ultrasonic7
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Нет, проверил, такой вариант не подходит. В этом случае индекс выходит за пределы счетчика массива. Нужно каждый раз копировать перезаписывать прежние 100 значений в l_VPUSubList следующими 100 значениями из l_TotalVPUList.
...
Рейтинг: 0 / 0
Копирование списков порциями
    #39730346
Фотография Elic
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
ultrasonic7прощеandrey_anonymousкляузу LIMIT
...
Рейтинг: 0 / 0
Копирование списков порциями
    #39730347
ultrasonic7
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Хотел написать не "копировать", а "перезаписывать"
...
Рейтинг: 0 / 0
Копирование списков порциями
    #39730372
Фотография Stax
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
ultrasonic7Нет, проверил, такой вариант не подходит. В этом случае индекс выходит за пределы счетчика массива. Нужно каждый раз копировать перезаписывать прежние 100 значений в l_VPUSubList следующими 100 значениями из l_TotalVPUList.

каждые 100 записей indSub надо сбрасывать indSub:=1;

ps
к-во записей всегда кратно 100?

.....
stax
...
Рейтинг: 0 / 0
Копирование списков порциями
    #39730444
ultrasonic7
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Staxк-во записей всегда кратно 100?

Да.
...
Рейтинг: 0 / 0
Копирование списков порциями
    #39730493
Фотография Stax
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
ultrasonic7Staxк-во записей всегда кратно 100?

Да.

есть мнение что Вы обрабатываете не 100, а 99 записей (indTotal := indTotal + 1; IF MOD (indTotal, 100) = 0 -- Каждые 100 значений)

зы
повторно, в IF счетчик надо сбрасывать

.....
stax
...
Рейтинг: 0 / 0
Копирование списков порциями
    #39730597
ultrasonic7
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Staxповторно, в IF счетчик надо сбрасывать
.....
stax
Да, надо это учесть.
...
Рейтинг: 0 / 0
Копирование списков порциями
    #39730639
Фотография andrey_anonymous
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Утомительная какая-то тема.
Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
DECLARE
  cursor c_data is -- тут запрос к данным
    select ROWNUM  VPU_NUM 
      from dual connect by level < 1000;

  type t_numtbl is table of c_data%rowtype index by pls_integer;
  l_VPUList t_numtbl;

  c_batch_size constant integer := 100; -- размер пачки
  start_time TIMESTAMP(6);
  exec_length INTERVAL DAY TO SECOND;

BEGIN
  open c_data;
  loop
    fetch c_data bulk collect into l_VPUList limit c_batch_size;
    start_time := SYSTIMESTAMP;
    for i in 1..l_VPUList.count() loop
      --Здесь какие-то действия с этими 100 значений
      null;
    end loop;
    exec_length := SYSTIMESTAMP - start_time;
    dbms_output.put_line('Обработано '||l_VPUList.count||' элементов; Продолжительность обработки: '||exec_length);
  exit when l_VPUList.count < c_batch_size;
  end loop;  
END;

...
Рейтинг: 0 / 0
Копирование списков порциями
    #39730648
Фотография Stax
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
andrey_anonymous,

Код: plsql
1.
2.
    for i in 1..l_VPUList.count() loop
    end loop;


не нужен

....
stax
...
Рейтинг: 0 / 0
Копирование списков порциями
    #39730651
Фотография andrey_anonymous
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Staxandrey_anonymous,

Код: plsql
1.
2.
    for i in 1..l_VPUList.count() loop
    end loop;


не нужен
Там "какие-то действия", а ТС цикл по коллекции формирует как Бог на душу положит - вылетит опять за границы, напишет нам "случилась ошибка" - гадай потом...
...
Рейтинг: 0 / 0
Копирование списков порциями
    #39730656
Фотография Stax
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
andrey_anonymousТам "какие-то действия",


автор а мне нужно копировать в l_VPUSubList порциями по 100 и для каждой итерации цикла вызывать процедуру, у которой входной параметр SYS.ODCINUMBERLIST и условия запуска требуют, чтобы в нём было 100 значений.

.....
stax
...
Рейтинг: 0 / 0
Копирование списков порциями
    #39730678
Фотография andrey_anonymous
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Staxandrey_anonymousТам "какие-то действия",

авторвходной параметр SYS.ODCINUMBERLIST и условия запуска требуют, чтобы в нём было 100 значений.

Просмотрел.
Надо тогда тип коллекции обратно поменять :)
...
Рейтинг: 0 / 0
Копирование списков порциями
    #39731554
ultrasonic7
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
В результате сделал так. Фетч происходит прямо в SYS.ODCINUMBERLIST, а внутренний цикл получается ненужным.
Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
DECLARE
  cursor c_data is -- тут запрос к данным
    select VPU_NUM 
    from SCHEMA_NAME.TABLE_NAME;

  l_VPUList SYS.ODCINUMBERLIST := SYS.ODCINUMBERLIST();

  c_batch_size constant integer := 100; -- размер пачки
  start_time TIMESTAMP WITH TIME ZONE;
  total_start_time TIMESTAMP WITH TIME ZONE;
  exec_length INTERVAL DAY TO SECOND;
  total_exec_length INTERVAL DAY TO SECOND;

BEGIN
  l_VPUList.extend(c_batch_size);
  total_start_time := SYSTIMESTAMP;
  open c_data;
  loop
    fetch c_data bulk collect into l_VPUList limit c_batch_size;
    start_time := SYSTIMESTAMP;
    SCHEMA_NAME.PACKAGE_NAME.PROC_NAME(param_in => l_VPUList);
    exec_length := SYSTIMESTAMP - start_time;
    dbms_output.put_line('Обработано '||l_VPUList.count||' элементов; Продолжительность обработки - часы:минуты:секунды: '||exec_length);
  exit when l_VPUList.count < c_batch_size;
  end loop;
  total_exec_length := SYSTIMESTAMP - total_start_time;
  dbms_output.put_line('Общая продолжительность обработки - часы:минуты:секунды: '||total_exec_length);  
END;
...
Рейтинг: 0 / 0
Копирование списков порциями
    #39731557
ultrasonic7
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Спасибо всем ответившим.
...
Рейтинг: 0 / 0
Копирование списков порциями
    #39731706
Фотография Stax
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
ultrasonic7,

SCHEMA_NAME.PACKAGE_NAME.PROC_NAME(param_in => l_VPUList); может отработать на пустой набор

.....
stax
...
Рейтинг: 0 / 0
Копирование списков порциями
    #39732466
ultrasonic7
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Stax,
Да, есть такое. После обработки последних 100 элементов из 10000:
Обработано 100 элементов; Продолжительность обработки - часы:минуты:секунды: +00 00:00:00.210193
обрабатывается 0 элементов:
Обработано 0 элементов; Продолжительность обработки - часы:минуты:секунды: +00 00:00:00.007318
Какую проверку добавить, чтобы список из 0 элементов не обрабатывался?
Так не помогает:
Код: plsql
1.
2.
IF l_VPUList IS NOT NULL THEN
      SOME_PROC(iDocIDs => l_VPUList);


так тоже:
Код: plsql
1.
2.
IF l_VPUList.COUNT > 0 THEN
      SOME_PROC(iDocIDs => l_VPUList);
...
Рейтинг: 0 / 0
Копирование списков порциями
    #39732469
ultrasonic7
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
так тоже не помогает
Код: plsql
1.
IF c_data%ROWCOUNT > 0 THEN
...
Рейтинг: 0 / 0
Копирование списков порциями
    #39732476
ultrasonic7
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Сам себе ответил. Надо было сделать так:
Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
DECLARE
  cursor c_data is
    select VPU_NUM 
    from SCHEMA_NAME.TABLE_NAME;

  l_VPUList SYS.ODCINUMBERLIST := SYS.ODCINUMBERLIST();

  c_batch_size constant integer := 100; -- размер пачки
  start_time TIMESTAMP WITH TIME ZONE;
  total_start_time TIMESTAMP WITH TIME ZONE;
  exec_length INTERVAL DAY TO SECOND;
  total_exec_length INTERVAL DAY TO SECOND;

BEGIN
  l_VPUList.extend(c_batch_size);
  total_start_time := SYSTIMESTAMP;
  open c_data;
  loop
    fetch c_data bulk collect into l_VPUList limit c_batch_size;
    IF c_data%FOUND THEN
      start_time := SYSTIMESTAMP;
      SCHEMA_NAME.PACKAGE_NAME.PROC_NAME(param_in => l_VPUList);
      COMMIT;
      exec_length := SYSTIMESTAMP - start_time;
      dbms_output.put_line('Обработано '||l_VPUList.count||' элементов; Продолжительность обработки - часы:минуты:секунды: '||exec_length);
    END IF;
  exit when l_VPUList.count < c_batch_size;
  end loop;
  total_exec_length := SYSTIMESTAMP - total_start_time;
  close c_data;
  dbms_output.put_line('Общая продолжительность обработки - часы:минуты:секунды: '||total_exec_length);  
END;
...
Рейтинг: 0 / 0
25 сообщений из 29, страница 1 из 2
Форумы / Oracle [игнор отключен] [закрыт для гостей] / Копирование списков порциями
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]