#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
. Это было бы довольно сложно, но это можно было бы сделать. Я не уверен, почему ваш initialSELECT
выполняется здесь с помощью динамического SQL, это, похоже, не имеет смысла. Еслиtemp_table1
не содержит ровно 5 столбцов, этот оператор завершится ошибкой. Вы просто хотели бы сделать статическийselect *
.2. Спасибо, это имеет смысл. Мой первоначальный оператор SELECT формируется динамически на основе столбцов, которые мне нужны для вставки / обновления целевой таблицы, только исходная таблица будет постоянной. Мой temp_table1 содержит 50 предопределенных столбцов, и у меня есть сопоставление для каждой целевой таблицы в таблице метаданных. Таким образом, я могу использовать 5 столбцов для одной целевой таблицы, в то время как другие могут использовать 20 и т.д.,