При передаче RECORD в качестве параметра ошибка: PLS-00306: wrong number or types of arguments in call to 'F'?
Есть такой код:
CREATE OR REPLACE PACKAGE pkg_test IS
TYPE trec is RECORD(c1 number);
FUNCTION f (r trec) RETURN VARCHAR2;
END pkg_test;
/
CREATE OR REPLACE PACKAGE BODY pkg_test IS
FUNCTION f (r trec) RETURN VARCHAR2 IS
BEGIN
RETURN 'a';
END f;
END pkg_test;
/
DECLARE
TYPE trec IS RECORD (c1 NUMBER);
rec trec;
var VARCHAR2(15);
BEGIN
rec.c1 := 1;
var := pkg_test.f (rec);
END;
/
При выполнении анонимного блока получаю эту ошибку:
PLS-00306: wrong number or types of arguments in call to 'F'
Почему так, ведь типы записей полностью идентичны?
Свободный перевод вопроса what is wrong passing a record type as parameter от участника @mikcutu
Ответы (2 шт):
Тип записи, который объявлен в анонимном блоке (local type) и в пакете (public item), выглядят одинаково, но PL/SQL это строго типизированный язык, и оба типа записи совершенно независимы и несовместимы. Что по этому поводу говорит документация:
A RECORD type defined in a package specification is incompatible with an identically defined local RECORD type.
Надо или напрямую воспользоваться типом из пакета (r1), или, если его имя не устраивает, создать локальный подтип записи (r2) совместимый с пакетным.
Рабочий пример:
declare
subtype trec is pkg_test.trec;
r1 pkg_test.trec;
r2 trec;
var varchar2(15);
begin
r1.c1 := 1;
var := pkg_test.f (r1);
r2.c1 := 1;
var := pkg_test.f (r2);
end;
/
PL/SQL procedure successfully completed.
Начиная с выпуска 18c появился новый тип выражений qualified expression.
Попрежнему надо указывать все поля записи, но не надо создавать отдельную переменную только для копирования полей, то есть синтаксис упростился.
Простой пример для наглядности - так надо было раньше:
declare
type trec is record (c1 int, cn int);
lr trec ;
pr pkg_test.trec;
ret char (1);
begin
lr.c1 := 0;
lr.cn := 1;
pr.c1 := lr.c1;
pr.cn := lr.cn;
ret := pkg_test.f (pr);
end;
/
PL/SQL procedure successfully completed.
Так можно теперь:
declare
type trec is record (c1 int, cn int);
r trec := trec (0,1);
ret varchar2(15);
begin
ret := pkg_test.f (pkg_test.trec (c1=>r.c1, cn=>r.cn));
end;
/
PL/SQL procedure successfully completed.