Проблема в insert, не хочет по циклу вставлять больше одной записи

Вечер добрый, нужна помощь, нужно привязать 2 создаваемые карты на одного человека, но почему то цикл или второй инсерт игнорируют вставку и сразу идут на выход, подскажите, что можно сделать? Суть задания в том, чтобы для одного аккаунта (который есть в базе) создать 1-2 карты, ни больше, ни меньше, но создается всего одна запись. Как только записи вставляются в таблицы, им автоматически присваивается свой id. В функции creating_bank_cards я пробовал и через for (for x in 1..l_kol_card) и через exit when (exit when l_kol_card > p_kol_card), и даже (if l_kol_card = 2), который представлен ниже. Нет проблем просто сделать 2-а insert-а с одинаковыми данными в таблицу, а если через функцию, то пропускает второй цикл (второй insert). p.s. Если заметите не используемые переменные, это так и задумано. Если появятся непонятки или предложения по оптимизации, пишите.

create or replace 
function checking_for_availability(
  p_client_id clients.clientid%type
, p_day deposits.depositdays%type
, p_symm deposits.depositsum%type
, p_val depositrecommendations.currencyname%type
, p_nom_dog deposits.dog_num%type
, p_kol_card integer default 1
) return varchar2
is
  l_count number;
  l_ststys varchar2(500);
  l_nom_card number;
begin
  if p_kol_card >= 3 then-- проверяю количество карт
    l_ststys := 'Не больше 2х карт на аккаунт';
    return l_ststys;
  elsif p_kol_card < 1 then
    l_ststys := 'Не указано количество карт, добавьте количество карт';
    return l_ststys;
  else
    select count (*)-- проверка на наличие записей по клиенту
    into l_count
    from clients c
    where c.clientid = p_client_id;
   
    if l_count = 0 then-- если клиента нет в бд, то нового не создаю
      l_ststys := 'Не создано';
    else-- если клиент есть, то иду в функцию
      l_nom_card := creating_bank_cards(p_client_id, p_day, p_symm, p_val, p_nom_dog, p_kol_card);
      l_ststys := 'Cоздано';
    end if;
    return l_ststys;
  end if;
end;
create or replace 
function creating_bank_cards (-- создание карты на аккаунт
  p_client_id clients.clientid%type
, p_day deposits.depositdays%type
, p_symm deposits.depositsum%type
, p_val depositrecommendations.currencyname%type
, p_nom_dog deposits.dog_num%type
, p_kol_card integer 
) return number
is
  l_random1 integer;
  l_card_id cards.cardid%type;
  l_kol_card integer default 1;
  l_acc_id number;
begin
  l_random1 := dbms_random.value(100,999);-- ставлю случайное значение для цвц
  l_acc_id := account_insert_deposin(p_client_id, p_val, p_day);-- по входным параметрам создаю аккаунт для вклада, выводится аккаунт id
  insert into cards(
        cardnomer,
        expiremonth,
        expireyear,
        cardholdername,
        cvc,
        cardstatus
        ,accountid
      ) values (
        lpad(p_client_id,16,0)
      , extract(month from sysdate+1125) 
      , extract(year from sysdate+1125)
      , 'name p_client_id '||p_client_id
      , l_random1
      , 1
      , l_acc_id)
              
        returning cardid into l_card_id;
        return l_card_id;
        
  if l_kol_card = 2 then
    l_random1 := dbms_random.value(100,999);
    insert into cards(
        cardid,
        cardnomer,
        expiremonth,
        expireyear,
        cardholdername,
        cvc,
        cardstatus,
        accountid
      ) values (
        l_card_id + 1
      , lpad(p_client_id,16,0)
      , extract(month from sysdate+1125) 
      , extract(year from sysdate+1125)
      , 'name p_client_id '||p_client_id
      , l_random1
      , 1
      , l_acc_id)
      returning cardid into l_card_id;
        return l_card_id;
  end if;
end;
create or replace 
function account_insert_deposin( --создание депозита
  p_client_id clients.clientid%type
, p_curr_name accounts.currencyname%type
, p_days      number
) return number 
is
  l_acc_nom   accounts.accountnomer%type;
  l_count_acc number;
  l_account_id accounts.accountid%type;
begin
  select count(*)-- смотрю, есть ли вклад по данному человеку
    into l_count_acc
    from accounts a
   where a.accountid = p_client_id;
   
   l_count_acc := l_count_acc + 1;--номер использую в номере аккаунта

  if p_days <= 30 then
    l_acc_nom := '42302';
  elsif p_days between 31 and 90 then
    l_acc_nom := '42303';
  elsif p_days between 91 and 180 then
    l_acc_nom := '42304';
  else
    l_acc_nom := '42305';
  end if;

  l_acc_nom := l_acc_nom 
  || p_curr_name 
  || lpad(p_client_id, 10, '0')
  || lpad(l_count_acc, 2, '0');
  
  insert into accounts (
              accountname,
              accountnomer,
              currencyname,
              clientid,
              accountstatus,
              dateopen
              )values (
              'Вклад физического лица на срок до '|| p_days ||' дней'
            , l_acc_nom
            , p_curr_name
            , p_client_id
            , 1
            , trunc(sysdate))
  
  returning accountid into l_account_id;
  return l_account_id;
  
end;


Ответы (2 шт):

Автор решения: s.vasilev

Оператор return заканчивает выполнение функции. Уберите return l_card_id в конец функции creating_bank_cards и тогда второй insert тоже сможет отрабатывать при l_kol_card равным двум. Только при создании более одной карты, будет возвращаться l_card_id второй карты.

→ Ссылка
Автор решения: 0xdb

ТС комментирует: да я запамятовал, что return сразу заканчивает действие.

Для того, чтобы наиболее быстро находить подобного рода ошибки, надо:

  • Создать минимальный воспроизодимый пример, т.е. пошагово убирать из кода всё лишнее, пока ошибка не исчезнет или не станет очевидной.

  • Рекомендуется компилировать с включенными предупреждениями компилятора (по умолчанию они выключены).

В итоге получится:

exec dbms_warning.set_warning_setting_string ('enable:all', 'session');

create or replace function f (par int) return int is
    ret int;
begin
    return ret;
    ret := par*10;
end;
/
Function F compiled

LINE/COL  ERROR
--------- -------------------------------------------------------------
1/1       PLW-05018: unit F omitted optional AUTHID clause; default value DEFINER used
5/5       PLW-06002: Unreachable code

Компилятор предупредил, что 5-я строчка кода никогда не будет выполнена.

→ Ссылка