Таблица, производная от Oracle, Вставка значений в новую таблицу

#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 лет назад, поэтому я застрял, пытаясь проанализировать это поле. Это, по крайней мере, дает мне возможность начать. Я создал несколько функций, типов, но всегда получал результаты странным образом. Я буду работать над этим и соответствующим образом обновлять вас!