#sql #oracle #oracle11g
Вопрос:
У меня есть функция, которая будет считывать список значений, разделенных запятыми, в поле. В результате выполнения этой функции будет создана производная таблица.
Пример:
производная таблица:
Теперь мне нужно вставить эти данные в новую/существующую таблицу. Я создал и тип объекта/пакет, в котором есть все столбцы из производной таблицы, однако я не уверен, как добавить/ссылаться на эти данные, чтобы их можно было вставить в новую/существующую таблицу.
Комментарии:
1. Я думаю, что вы путаете производные таблицы (запрос, из которого вы читаете) и вложенные таблицы (таблица в таблице). Вы хотите сохранить результат запроса, состоящий из обычных столбцов (чисел, дат, строк) и столбца вложенной таблицы. Вы хотите знать, как это сохранить. Правильно?
2. Извините, да, таблица внутри таблицы., извините, что я изначально не был ясен. Мне удалось проанализировать столбец, содержащий данные CSV. Мне пришлось создать функцию, которая анализировала бы это и НЕ считала запятые, которые были между двойными кавычками. Я смог сделать это прекрасно. Однако это создало встроенную таблицу в моей таблице. Мне нужно нормализовать эту встроенную таблицу в ее собственные столбцы. Я попытался обойти все это и использовать регулярные выражения, однако мне не удалось последовательно разрешить нули, а также оставить список запятых внутри двойных кавычек и все равно получить 48 столбцов, которые я ожидал.
Ответ №1:
Функции, возвращающие вложенную таблицу, могут быть преобразованы в обычные строки и столбцы путем выбора из функции таблицы TABLE
с помощью функции. (И в последних версиях Oracle TABLE
оператор необязателен.)
Например:
SQL> create or replace function get_columns return sys.odcivarchar2list is
2 begin
3 return sys.odcivarchar2list('355352', 'Yes');
4 end;
5 /
Function created.
SQL> select column_value from table(get_columns);
COLUMN_VALUE
--------------------------------------------------------------------------------
355352
Yes
Теперь эту функцию можно использовать где угодно, например, для вставки: insert into some_table select column_value from table(get_columns);
Ваше конкретное решение может быть более сложным, если результаты содержат несколько столбцов, или у вас несколько наборов результатов и т. Д. Отредактируйте свой вопрос с более подробной информацией о функциях и типах, если вам все еще нужна помощь.
Изменить: Ниже приведен полный пример хранения значений CSV в столбце, создания функции для преобразования CSV в VARRAY, вызова этой функции для поворота, а затем повторного поворота в несколько столбцов:
create table table_1
(
request_id number,
service varchar2(100),
method varchar2(100),
request_date date,
process_date date,
te_suid number,
status varchar2(100),
params varchar2(4000)
);
create or replace type params_varray is varray(48) of varchar2(4000);
--Example function that converts comma-separated lists into VARRAYS.
--(Not tested for nulls, consecutive commas, etc.)
create or replace function get_columns(p_params varchar2, p_delimiter varchar2) return params_varray is
v_array params_varray := params_varray();
begin
for i in 1 .. regexp_count(p_params, p_delimiter) 1 loop
v_array.extend;
v_array(v_array.count) := regexp_substr(p_params, '[^'||p_delimiter||'] ', 1, i);
end loop;
return v_array;
end;
/
insert into table_1 values(1,1,1,sysdate,sysdate,1,1,'1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48');
insert into table_1 values(2,2,2,sysdate,sysdate,2,2,'49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96');
--Convert CSV into multiple columns.
--
--Convert rows back into multiple columns.
select request_id, service, method, request_date, process_date, te_suid, status
,max(case when param_index = 1 then param_value else null end) value1
,max(case when param_index = 2 then param_value else null end) value2
,max(case when param_index = 3 then param_value else null end) value3
--Repeat for 4 through 48.
from
(
--Convert CSV to rows.
select request_id, service, method, request_date, process_date, te_suid, status,
row_number() over (partition by table_1.rowid order by rownum) param_index,
column_value param_value
from table_1
cross join get_columns(table_1.params, ',')
)
group by request_id, service, method, request_date, process_date, te_suid, status;
Вы можете запустить пример в db<>fiddle<>.
Но если у вас есть какой-либо выбор в этом вопросе, я настоятельно рекомендую вам денормализовать свою таблицу и никогда не хранить значения с разделителями в базе данных.
Комментарии:
1. Спасибо тебе, Джон. Я это понимаю. Я не уверен, как вернуться к исходной таблице для 7 столбцов. Например, в моем примере у меня есть 7 столбцов и производная таблица. Мне нужно все в одной строке, то есть 7 столбцов в начале и 48, которые являются частью производной таблицы. Использование инструкции table даст мне данные в производной таблице в формате строки, но мне нужно, чтобы эти данные были развернуты так, чтобы у меня было 2 строки и 55 столбцов (7 из обычного выбора 48 из производной таблицы).
2. Вот мой полный выбор: выберите.request_id, — 1 a.сервис, —2 a.метод, —3 a.request_date, —4 a.process_date, —5 a.te_suid, —6 a.статус —7 get_columns(a.параметры,’,’,'»‘) — имеет 48 строк, 2 столбца (индекс, значение) из table_1 a, ГДЕ.метод = ‘saveCobqResponse’ И параметры, такие как «55352% «И параметры, такие как» 21%»; Возвращаемые данные должны быть 2 строками, 55 столбцами, чтобы я мог выбрать/вставить в другую таблицу. Спасибо!
3. @user3874930 Будет ли вложенная таблица всегда содержать не более 48 строк или это значение динамическое? Динамический поворот значительно усложнил бы эту проблему.
4. ВСЕГДА 48. Могут быть значения null, но в производной таблице всегда должно быть 48 строк.
5. Спасибо тебе, Джон. Я хотел бы, чтобы команда изменила свой процесс и не хранила значения в формате CSV, но это наследие, и эта команда ушла более 5 лет назад, поэтому я застрял, пытаясь проанализировать это поле. Это, по крайней мере, дает мне возможность начать. Я создал несколько функций, типов, но всегда получал результаты странным образом. Я буду работать над этим и соответствующим образом обновлять вас!