Обязательно ли имя поля в record.FIELD быть литералом в цикле курсора? - PullRequest
0 голосов
/ 06 июня 2018

Я готовлю процедуру, которая будет извлекать данные из нескольких таблиц и выводить файл .csv, но у меня есть непреодолимая проблема для оптимизации кода.Ниже приведена иллюстрация проблемы.

Этот код работает прямо:

declare
    cursor cur_company is
       select company_name, no_employees
       from company;
    line_out varchar2(200);
 begin
    for rec in cur_company loop
       line_out := '';
       line_out := line_out || rec.company_name || ',';
       line_out := line_out || rec.no_employees;
       dbms_output.put_line(line_out);
    end loop;
end;
/

PL/SQL procedure successfully completed.

USCABLES,250
KODAK,2500
KLM,5000
HAMBRO,2000
FORD,8000
CITYBANK,3000
DISNEY,2500

В этом примере каждая запись имеет только два поля.Но процедура, над которой я работаю, имеет дело с десятками полей, скажем, 60, и, таким образом, одно и то же конкатенационное повторение будет повторяться 60 раз:

  for rec in cur_company loop
     line_out := '';
     line_out := line_out || rec.field1 || ',';
     line_out := line_out || rec.field2 || ',';
     ...
     line_out := line_out || rec.field60;
     ...
  end loop;

Поэтому код не выглядит визуально.Я думал о внедрении еще одного цикла для циклического прохождения всех полей.Ниже приведен код с числом строк кода, меньшим 60, но с ошибкой:

declare
   cursor cur_company is
      select company_name, no_employees
      from company;
   line_out varchar2(200);
   headerset varcharlist := varcharlist('COMPANY_NAME', 'NO_EMPLOYEES');
begin
   for rec in cur_company loop
      line_out := '';
      for ctr in 1..headerset.count loop
         if ctr = headerset.count then
            line_out := line_out || rec.headerset(ctr);
         else
            line_out := line_out || rec.headerset(ctr) || ', ';
         end if;
      end loop;
      dbms_output.put_line(line_out);
   end loop;
end;
/

...
ORA-06550: line 12, column 41:
PLS-00302: component 'HEADERSET' must be declared
...

Может ли быть проблема с массивом HEADERSET?Ниже показано, что с массивом все в порядке:

declare
   headerset varcharlist := varcharlist('COMPANY_NAME', 'NO_EMPLOYEES');
begin
   for ctr in 1..headerset.count loop
      dbms_output.put_line(headerset(ctr));
   end loop;
end;
/

PL/SQL procedure successfully completed.

COMPANY_NAME
NO_EMPLOYEES

Или это связано с прямым использованием массива для именования полей?Я пытался поместить элемент массива в переменную varchar2 перед его использованием.Но возникла такая же ошибка:

declare
   cursor cur_company is
      select company_name, no_employees
      from company;
   line_out varchar2(200);
   headerset varcharlist := varcharlist('COMPANY_NAME', 'NO_EMPLOYEES');
   col_name varchar2(20);
begin
   for rec in cur_company loop
      line_out := '';
      for ctr in 1..headerset.count loop
         col_name := headerset(ctr);
         if ctr = headerset.count then
            line_out := line_out || rec.col_name;
         else
            line_out := line_out || rec.col_name || ', ';
         end if;
      end loop;
      dbms_output.put_line(line_out);
   end loop;
end;
/

...
ORA-06550: line 14, column 41:
PLS-00302: component 'COL_NAME' must be declared
...

Теперь мне кажется, что при циклическом просмотре полей записи курсора PL / SQL принимает только литералы для имени поля и переменныхне признаютсяЭто правда?Есть ли способ обойти это ограничение, чтобы уменьшить беспорядок в коде?

1 Ответ

0 голосов
/ 07 июня 2018

Вы не можете ссылаться на такой запрос.Вы можете использовать динамический SQL, но это, вероятно, плохая идея.Я бы предложил просто перечислить имена столбцов в вашей агрегации.Если вы хотите ускорить его, вы можете запросить от ALL_TAB_COLS, чтобы получить список столбцов в вашей таблице.

...