Проблема в 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 шт):
Оператор return заканчивает выполнение функции.
Уберите return l_card_id в конец функции creating_bank_cards и тогда второй insert тоже сможет отрабатывать при l_kol_card равным двум.
Только при создании более одной карты, будет возвращаться l_card_id второй карты.
ТС комментирует: да я запамятовал, что 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-я строчка кода никогда не будет выполнена.