Oracle - две петли в процедуре - PullRequest
0 голосов
/ 30 марта 2020

Мне нужна помощь в написании Oracle PL / SQL процедуры, которая должна выполнять следующее:

  1. процедура вызывается из триггера после обновления поля в одна таблица с входным параметром B-блок или D-активировать (это уже сделано)

  2. процедура должна сначала открыть один курсор, который будет перехватывать номера счетов клиента и открывать все oop, который будет обрабатывать учетную запись по учетной записи

  3. эта одна учетная запись должна быть перенаправлена ​​на другую l oop, которая будет перехватывать номера карт этого клиента для этой учетной записи (второй курсор) и когда в эту l oop номер карты должен использоваться в качестве входного параметра для хранимой процедуры, которая вызывается для блокировки / разблокировки этой карты - эта хранимая процедура уже существует, мне просто нужно вызвать ее

  4. процедуре не нужно возвращать никаких параметров, идея состоит в том, чтобы просто заблокировать / активировать номер карты клиента с уже записанной хранимой процедурой для этого

Должен ли я написать пакет для этого или просто процедуру? И как я могу написать один l oop в другом?

Ответы [ 2 ]

0 голосов
/ 31 марта 2020

Как указывало @EdStevens, вы не можете избежать обработки курсоров. Но вы можете избежать зацикливания структуры курсора внутри курсора. И неявный курсор открытия и закрытия для внутреннего. Запросы объединяются в простое соединение, а затем собираются в одну коллекцию. Для этого я создал RECORD, который будет содержать как номер счета, так и номер карты; затем коллекция этой записи. Затем курсор массово собирается в коллекцию. Ваш исходный код позволяет обрабатывать до 100000 карт, и хотя я являюсь поклонником массового сбора (при необходимости), я не поклонник заполнения памяти, поэтому я ограничиваю количество строк массового сбора для каждой выборки. К сожалению, здесь вводится конструкция al oop -within-l oop, но наказание не так велико, как у конструкции курсор внутри курсора. Ниже приведен результат.

 create or replace procedure blokiraj_proc (core_cust_id varchar2) as
    type acct_card_r 
         is record(
            acct_num test_kartice.rbs_acct_num%type
          , card_num test_kartice.card_num%type
          );
    type acct_card_array is table of acct_card_r; 
    acct_card_list acct_card_array; 

    k_acct_card_buffer_limit constant integer := 997;
    cursor c_acct_card(c_cust_id varchar2) is
           select r.foracid 
                , k.card_num
             from test_racuni r
             left join test_kartice k 
                    on (k.rbs_acct_num = r.foracid)
            where r.cif_id = c_cust_id
            order by r.foracid 
                   , k.card_num;
begin 
    dbms_output.enable (buffer_size => null); -- enable dbms_output with size unlimited
    open c_acct_card(core_cust_id); 

    loop 
        fetch c_acct_card
         bulk collect 
         into acct_card_list
        limit k_acct_card_buffer_limit;

        for i in 1 .. acct_card_list.count
        loop
            dbms_output.put (acct_card_list(i).acct_num || ' ==> ');
            if acct_card_list(i).card_num is not null 
            then
                dbms_output.put_line (acct_card_list(i).card_num);
                blokiraj_karticu (acct_card_list(i).card_num);
            else
                dbms_output.put_line ('No card for this account');
            end if; 
        end loop; 

    -- exit buffer fetch when current buffeer is not full. As that means all rows 
    -- from cursor have been fetched/processed.
    exit when acct_card_list.count < k_acct_card_buffer_limit;   
    end loop;

    close c_acct_card;

end blokiraj_proc;

Ну, это просто другой подход. Если тебе будет лучше, отлично. Я также хочу повторить и расширить предупреждение Эда Стивенса о запуске этого из триггера. Если одна из таблиц здесь является таблицей, по которой сработал триггер, вы все равно получите исключение изменяющейся таблицы - вы не можете просто спрятать ее за процедурой. И даже если не много циклов для триггера.

0 голосов
/ 30 марта 2020

Я только что понял, что могу сделать это без курсоров в процедуре. Для простого примера:

create or replace procedure blokiraj_proc (core_cust_id varchar2,  kyc_blocked varchar2) as
type NumberArray is Array(100) of test_racuni.foracid%type;
type StringArray is Array (1000) of test_kartice.card_num%type;

accnt NumberArray;
card_number StringArray;

begin  
    select foracid bulk collect into accnt from test_racuni where cif_id = core_cust_id;

    for i in accnt.first..accnt.last 
    loop
        select card_num  bulk collect into card_number from test_kartice where rbs_acct_num = accnt(i);
        dbms_output.enable (100000);
        dbms_output.put_line (accnt(i));

        for j in 1..card_number.count 
        loop
            dbms_output.put_line (card_number(j));
            blokiraj_karticu (card_number(j));
        end loop;
    end loop;

end;

Это лучший подход, чем курсоры? И почему dbms_output ничего не печатает, когда я запускаю процедуру?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...