Как выполнить итерацию по именам атрибутов локально объявленных коллекций?

Как выполнить итерацию по именам атрибутов локально объявленных коллекций?

Пробую так, но работает не так, как ожидалось:

declare
   type books is record
        (title   varchar(50)  := 'First Book'
        ,author  varchar(50)  := 'Me'
        ,subject varchar(100) := 'Simple ones'
        ,book_id number       := 94321
        );      
   type table_of_books is table of books;
   list_of_books table_of_books;
   
   CURSOR c IS 
       SELECT COLUMN_NAME 
       FROM ALL_COL_COMMENTS 
       WHERE table_name='list_of_books';
begin
  dbms_output.enable;
  list_of_books := table_of_books();
  list_of_books.extend(1);
  list_of_books(1) := books();
  
  FOR current_field IN c LOOP 
      dbms_output.put_line(current_field.column_name); 
  END LOOP;
end;
/

Этот код выполняется, но не выводит ничего.


PS Версия Oracle 19c.

Свободный перевод вопроса Iterate on column names of locally defined table от участника @user5507535


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

Автор решения: 0xdb

Короткий ответ - так как в вопросе, сделать нельзя. Атрибуты типов, объявленныx в PL/SQL блоке, не сохраняются как метаданные в словаре данных БД.


Возможное решение -- получить имена столбцов, в результате т.н. unnesting query c коллекцией в операторе TABLE. Но для этого коллекция должна быть известна SQL парсеру, т.е. как минимум объявлена в пакете. Данные в коллекции в этом случае не нужны, достаточно только открыть курсор:

create or replace package pack as 
    type book is record (
        title varchar(50),
        author varchar(50),
        subject varchar(100),
        book_id number);      
    type books is table of book index by pls_integer;
end;
/
declare
    lib pack.books :=  pack.books ();
    nc number; 
    cols number;
    ds dbms_sql.desc_tab;
    rc sys_refcursor;
begin
    open rc for select * from table (lib);
    nc := dbms_sql.to_cursor_number (rc);
    dbms_sql.describe_columns (nc, cols, ds);
    dbms_sql.close_cursor (nc);
    for i in 1..cols loop dbms_output.put_line (ds(i).col_name);
    end loop;
end;
/

Результат:

TITLE
AUTHOR
SUBJECT
BOOK_ID
→ Ссылка