Можно ли не передавать параметры, которые не имеют значения, по умолчанию?
Есть процедура с 21-им параметрoм, некоторые из них используются для передачи данных, другие - для получения или передачи\получения (в зависимости от обстоятельств). Причем, не все IN параметры обязательно передавать.
Выглядит, условно, так:
procedure FOO_BAR(
a in number,
b in number,
c in out date,
d in boolean,
e in varchar2,
...
z in varchar2
) is
begin
otherProc(
a, b, c, d, e, ..., z
);
end;
Внутри нее вызывается другая процедура, в которую передаются эти параметры, она что-то делает, и в некоторые из них пишет результат.
К FOO_BAR я обращался из C#, создавал параметры через OracleParameter и тем, кому не обязательно задавать значение, просто не указывал Value. Но сами переменные-параметры при вызове передавал.
Теперь мне нужно как-то вызвать эту FOO_BAR не из C#-кода, а из другой хранимой процедуры, получить и вернуть значение параметра, например, c.
Проблема в том, что я не хочу объявлять 20 переменных под параметры, которые мне не нужны и передавать их только "чтобы было". Хочу что-то такое:
function FOO_BAR_LESS_PARAM(
id number
) return date is
newDate date;
begin
FOO_BAR(
a => id,
c => newDate
);
return newDate;
end FOO_BAR_LESS_PARAM;
Т.е., передал только важный параметр, который нужен для расчетов, получил дату в переменную и вернул ее:
set serveroutput on;
declare
id number := 111222;
resDate date;
begin
resDate := FOO_BAR_LESS_PARAM(id);
dbms_output.put_line('resDate: ' || resDate);
end;
Можно ли как-то сделать это?
Желательно без задания значений по умолчанию, потому что я не знаю что будет, если в какой-нибудь параметр "b" передать 0, а не "ничего". Как я упоминал выше, в C# я вообще не указывал никакого значения и оно внутри там само как-то это интерпретировало. Сейчас ошибка о недостаче параметров при вызове FOO_BAR.
Ответы (2 шт):
Да, это возможно. Просто надо указать значение параметра по умолчанию NULL.
create or replace package pack as
procedure foo (a in number, b in number, c in out date);
procedure bar (a in number, b in number := null, c in out date);
end;
/
create or replace package body pack as
procedure foo (a in number, b in number, c in out date) is
begin null;
end;
procedure bar (a in number, b in number := null, c in out date) is
begin null;
end;
end;
/
Посмотрите последние два рабочих вызова, они полностью идентичны, но во втором параметр передавать необязательно:
declare
c date := date'2021-07-13';
begin
--pack.foo (1, c=>c);
--PLS-00306: wrong number or types of arguments in call to 'FOO'
pack.foo (1, b=>null, c=>c);
pack.bar (1, c=>c);
end;
/
PL/SQL procedure successfully completed.
Без задания значений по умолчанию для неиспользующихся аргументов можно создавать процедуры с переменным количеством аргументов. В этом случае, аргументы реализуются через:
- тип данных - запись (не указанные аргументы имеют значение
NULL) - или ассоциативную коллекцию (не указанные аргументы просто отсутствуют)
Оба способа показанны в этом воспроизводимом примере:
declare
type varargs is record (arg1 int, arg2 int, arg3 varchar2(8), arg4 date);
type kwargs is table of varchar2 (32) index by varchar2 (32);
procedure foo (va varargs) is --, rc out sys_refcursor
args varchar2(32767) := va.arg1||','||
case when va.arg2 is not null then va.arg2||','end||
case when va.arg3 is not null then va.arg3||','end||
va.arg4;
begin
dbms_output.put_line ('args='||args);
end;
procedure foo (kw kwargs) is --, rc out sys_refcursor
args varchar2(32767) := kw('arg1')||','||
case when kw.exists('arg2') then kw('arg2')||','end||
case when kw.exists('arg3') then kw('arg3')||','end||
kw('arg4');
begin
dbms_output.put_line ('args='||args);
end;
begin
foo (varargs ( arg1 =>1, arg3 =>'abc', arg4 =>date'2021-07-19'));
foo ( kwargs ('arg1'=>2, 'arg2'=>'def', 'arg4'=>date'2021-07-20'));
end;
/
Вывод результата:
args=1,abc,2021-07-19 00:00:00
args=2,def,2021-07-20 00:00:00