2010-10-05 2 views
2

У меня возникла небольшая проблема с куском массива sql, который я надеялся, что вы сможете помочь.Проблема с выпуском Oracle Bulk Collect

С помощью следующего кода:

declare 
    cursor c1 
    is 
    select customer,product 
    from products; 

    type type_cust is table of products.customer%type; 
    type type_prod is table of products.product%type; 

    v_array_cust type_cust; 
    v_array_prod type_prod; 
begin 
    open c1; 
    loop 
     fetch c1 
     into v_array_cust, v_array_prod 
     limit 1000; 

     exit when c1%notfound; 

     for i in 1..v_array_cust.count 
     loop 
      --Do some processing here. 
     end loop; 
    end loop; 
end; 
/

Курсор c1 возвращает 53166 строк.

Однако код обрабатывает 53000 строк и затем заканчивается. Похоже, что когда вы собираетесь восстановить последние 166 записей, есть какой-то провал.

Будет ли возврат возврата% notfound, если он найдет менее 1000 записей? Должен ли я переместить выход в конец цикла? (Я собираюсь попробовать это, но он глубоко в куске кода, который занимает 3 часа, чтобы добраться до точки отказа.)

Заранее спасибо.

ответ

9

ОК, ну, лучше, чем глупо, чем я уже сделал, дал мне ответ, который вы не должны использовать% notfound with limit.

Отметьте here для получения пояснения.

+0

+1 для нахождения ответа самостоятельно. –

+0

Кстати, я не согласен с этой статьей. Просто неправильно говорить «не использовать% notfound with limit». Нет ничего плохого в использовании% notfound с лимитом, если вы положите их в правильном порядке (см. Мой ответ). –

1

Извините, что это тот, кто сказал это, но спасибо! курсоры! ... так, как вы написали это, вы пришли из линейного программирования. Вы рассматривали решение, основанное на множестве?

+0

Это немного самонадеянно, так как он не указывает, что делает бит «Сделай немного обработки здесь». Это может быть что-то, что невозможно или неэффективно делать в SQL. Кроме того, он забирает в память 1000 строк за раз, что обычно является очень эффективным методом обработки больших наборов данных в PL/SQL. –

+0

Цикл - это цикл - это цикл;) Просто нужно задать вопрос о том, «нужен ли мне цикл/курсор». – Twelfth

+0

Я исхожу из линейного фона программирования. Но это не мой код - это устаревший код, который я поддерживаю. Есть ли другой вариант? Я не понимаю, что вы подразумеваете под «установленным решением». – gnuchu

4

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

open c1; 
loop 
    fetch c1 
    into v_array_cust, v_array_prod 
    limit 1000; 

    -- the count will be 0 if no rows were found, so this loop will do nothing. 
    for i in 1..v_array_cust.count 
    loop 
     --Do some processing here. 
    end loop; 

    -- exit now if the last fetch got the last set of rows 
    exit when c1%notfound; 
end loop; 
close c1; 
+0

Спасибо. Я пошел с 'exit, когда v_array_cust.count = 0', который работает так же хорошо. – gnuchu

+1

Да, это тоже сработает - не имеет большого значения, но ваш метод будет включать лишнюю ненужную выборку из курсора (но это только я придирчивый) –

+0

@JeffreyKemp Вы бы сказали, что это не материал? Давайте сделаем вид, что этот цикл находится внутри другого цикла. –