Объявление таблицы типов rowtype с динамической таблицей

#oracle #dynamic #types

#Oracle #динамический #типы

Вопрос:

У меня есть временная таблица TEMP_TABLE1 , в которую временно хранятся данные и, наконец, объединяются с основной таблицей. Я использую это как общую таблицу для нескольких целевых таблиц разной структуры.

  COL1               VARCHAR2(2000)
 COL2               VARCHAR2(2000)
 COL3               VARCHAR2(2000)
 COL4               VARCHAR2(2000)
 COL5               VARCHAR2(2000)
 COL6               VARCHAR2(2000)
 COL7               VARCHAR2(2000)
 COL8               VARCHAR2(2000)
 COL9               VARCHAR2(2000)
 COL10              VARCHAR2(2000)
 COL11              VARCHAR2(2000)
 COL12              VARCHAR2(2000)
 ..
 COL40              VARCHAR2(2000)
 COL41              DATE
 COL42              DATE
  

Теперь у меня есть требование вставить, но отбросить некоторые нежелательные / ошибочные строки.
Итак, на данный момент у меня есть приведенный ниже рабочий код для одной примерной целевой таблицы.

 declare
  type l_array is table of TEMP_TABLE3%rowtype;
       l_rec_data l_array;
       l_sql      VARCHAR2(200);
       l_start    NUMBER:=1;
       j NUMBER;
 begin
        l_sql := 'select COL1,COL2,COL3,COL4,COL5 FROM TEMP_TABLE1';
        execute immediate l_sql bulk collect into l_rec_data;
        DBMS_OUTPUT.PUT_LINE(l_rec_data.COUNT);
        begin 
        loop 
         begin 
          forall i in l_start .. l_rec_data.count 
          insert into TEMP_TABLE3 (COL1,COL2,COL3,COL4,COL5) values ( l_rec_data(i).COL1,l_rec_data(i).COL2,l_rec_data(i).COL3,l_rec_data(i).COL4,l_rec_data(i).COL5); 
          EXIT; 
          exception 
            when DUP_VAL_ON_INDEX THEN
            dbms_output.put_line( 'DUP_VAL_ON_INDEX row index = ' || (l_start sql%rowcount) ||  ' ' || sqlerrm ); 
            j:=l_start sql%rowcount;
            UPDATE TEMP_TABLE3 SET COL2=l_rec_data(j).COL2, COL3=l_rec_data(j).COL3, COL4=l_rec_data(j).COL4, COL5=l_rec_data(j).COL5 WHERE COL1=l_rec_data(j).COL1;
            l_start := l_start   1; 
            when others then 
            dbms_output.put_line( 'Bad row index = ' || (l_start sql%rowcount) ||  ' ' || sqlerrm ); 
            l_start := l_start   sql%rowcount   1; 
          end; 
         end loop; 
         end;
END;
  

Тем не менее, я хочу динамически объявлять l_array для различных таблиц.
Пример: я мог бы захотеть объявить l_array как таблицу ( TEMP_TABLE3%rowtype — несколько строк), скажем, что-то вроде приведенного ниже :

 type l_array is table of TABLE(COL1,COL2,COL3,COL4)%rowtype; 
  

Комментарии:

1. %ROWTYPE должен быть привязан к определенной таблице. Он не может быть динамическим. Если вы настроены решительно, вы можете динамически создавать весь блок PL / SQL в виде строки и выполнять это через EXECUTE IMMEDIATE . Это было бы довольно сложно, но это можно было бы сделать. Я не уверен, почему ваш initial SELECT выполняется здесь с помощью динамического SQL, это, похоже, не имеет смысла. Если temp_table1 не содержит ровно 5 столбцов, этот оператор завершится ошибкой. Вы просто хотели бы сделать статический select * .

2. Спасибо, это имеет смысл. Мой первоначальный оператор SELECT формируется динамически на основе столбцов, которые мне нужны для вставки / обновления целевой таблицы, только исходная таблица будет постоянной. Мой temp_table1 содержит 50 предопределенных столбцов, и у меня есть сопоставление для каждой целевой таблицы в таблице метаданных. Таким образом, я могу использовать 5 столбцов для одной целевой таблицы, в то время как другие могут использовать 20 и т.д.,