Моя первая рекомендация - использовать динамический SQL для генерации большого количества тупого кода вместо небольшого количества умных PL / SQL.Если генерация кода не работает, вы можете использовать ANYDATA и ANYTYPE для создания отражения PL / SQL для динамической итерации элементов записи во время выполнения.
Генерация кода
Не напишите BIND_VARIABLE 100 раз, но создайте небольшую программу для генерации 100 строк кода для вас.Если данные в конечном итоге поступают из одной таблицы и переходят в другую таблицу, ввод и вывод могут быть предсказуемыми на основе представлений словаря данных, таких как DBA_TAB_COLUMNS.
Надеемся, что такой маленький запрос может помочь сгенерировать весь код дляодна таблица:
--Generate PL/SQL statements for binds.
select
'DBMS_SQL.BIND_VARIABLE(lvnInsertCursorId, '':RTTEXT'||column_id||'VC100'', lvaDBOBJDTLRecTab(i).'||column_name||');'
from dba_tab_columns
where owner = 'SOME_OWNER'
and table_name = 'SOME_TABLE'
order by 1;
Затем вы можете скопировать и вставить вывод в блок PL / SQL.Возможно, вам также понадобится предупреждение, например «не изменять, этот код автоматически генерируется процедурой CODE_TRON_2000».
Этот подход будет работать только в том случае, если код PL / SQL является предсказуемым на основе словаря данныхили другие метаданные.
Отражение PL / SQL
Нет чистого отражения PL / SQL для типов PL / SQL *, но есть простой обходной путь, если вы хотите создать типы записей какОбъекты SQL вместо.Если все ваши записи PL / SQL основаны на типах объектов, то для динамического доступа к атрибутам можно использовать ANYDATA и ANYTYPE.Типы объектов и типы записей PL / SQL очень похожи, поэтому преобразование одного в другое должно быть относительно безболезненным.
Например, если вы создаете тип объекта, который содержит число и строку:
create or replace type v_type is object(a number, b varchar2(1));
Этот (болезненный) блок PL / SQL показывает, как выполнить итерацию по всем записям коллекции, а затем выполнить итерацию по всем атрибутам в каждой записи.(В коде печатаются значения для, вам придется самостоятельно добавлять связующие части.)
declare
type v_nt_type is table of v_type;
v_values v_nt_type := v_nt_type(v_type(1, 'A'), v_type(2, 'B'));
begin
--For each record:
for i in 1 .. v_values.count loop
declare
v_anydata anydata := anydata.ConvertObject(v_values(i));
v_number number;
v_varchar2 varchar2(4000);
v_result pls_integer;
v_anytype anytype;
v_dummy_num pls_integer;
v_dummy_char varchar2(4000);
v_dummy_anytype anytype;
v_number_of_elements number;
begin
--Get the ANYTYPE and the number of elements.
v_result := v_anydata.getType(v_anytype);
v_result := v_anytype.getInfo
(
prec => v_dummy_num,
scale => v_dummy_num,
len => v_dummy_num,
csid => v_dummy_num,
csfrm => v_dummy_num,
schema_name => v_dummy_char,
type_name => v_dummy_char,
version => v_dummy_char,
numelems => v_number_of_elements
);
--For each element in the record:
for i in 1 .. v_number_of_elements loop
--Find the type of the element:
v_anydata.piecewise;
v_result := v_anytype.getAttrElemInfo(
pos => i,
prec => v_dummy_num,
scale => v_dummy_num,
len => v_dummy_num,
csid => v_dummy_num,
csfrm => v_dummy_num,
attr_elt_type => v_dummy_anytype,
aname => v_dummy_char);
--This is where you do something interesting with the values.
--(The same code merely prints the values.)
if v_result = dbms_types.typecode_number then
v_result := v_anydata.getNumber(num => v_number);
dbms_output.put_line(v_number);
elsif v_result = dbms_types.typecode_varchar2 then
v_result := v_anydata.getVarchar2(c => v_varchar2);
dbms_output.put_line(v_varchar2);
--TODO: Add other potential types here.
end if;
end loop;
end;
end loop;
end;
/
Результаты:
1
A
2
B
* Вы правы, что должно быть какой-то способ найти эту информацию времени выполнения, если отладчик ее получает.Но, насколько я знаю, PL / SQL не может извлечь эту отладочную информацию.Может быть, он доступен только для интерфейса OCI (?)?