我有一个JSON响应,在处理完响应后,我的输出如下:
column_variable := 'col1,col2,col3';
data_clob :=
"2017-10-14,abc,1,
2019-10-13,abc,12,
2019-10-12,abc,,
"
;
由于原始回复包含new line
的转义字符,data_clob
也已相应转换。
如何在oracle表中转换此逗号分隔值:
我的输出应如下所示:
col1 col2 col3
2017-10-14 abc 1
2019-10-13 abc 12
2019-10-12 abc null
我正在查看类似的问题,但我不想使用REGEXP_SUBSTR
因为我不知道我将在响应中获得的列数。
例如:column_variable
可能有'col1,col2,col3,col4,col5,col6'
;
我正在使用oracle 12.1.0.2.0
请帮忙!
答案 0 :(得分:1)
使用Polymorphic Table Functions
(Oracle 18c)实现它是非常简单的方法:
Dynamic CSV to Columns Converter: Polymorphic Table Function Example:
create or replace package csv_pkg as
/* The describe function defines the new columns */
function describe (
tab in out dbms_tf.table_t,
col_names varchar2
) return dbms_tf.describe_t;
/* Fetch_rows sets the values for the new columns */
procedure fetch_rows (col_names varchar2);
end csv_pkg;
和身体:
create or replace package body csv_pkg as
function describe(
tab in out dbms_tf.table_t,
col_names varchar2
)
return dbms_tf.describe_t as
new_cols dbms_tf.columns_new_t;
col_id pls_integer := 2;
begin
/* Enable the source colun for reading */
tab.column(1).pass_through := FALSE;
tab.column(1).for_read := TRUE;
new_cols(1) := tab.column(1).description;
/* Extract the column names from the header string,
creating a new column for each
*/
for j in 1 .. ( length(col_names) - length(replace(col_names,',')) ) + 1 loop
new_cols(col_id) := dbms_tf.column_metadata_t(
name=>regexp_substr(col_names, '[^,]+', 1, j),--'c'||j,
type=>dbms_tf.type_varchar2
);
col_id := col_id + 1;
end loop;
return dbms_tf.describe_t( new_columns => new_cols );
end;
procedure fetch_rows (col_names varchar2) as
rowset dbms_tf.row_set_t;
row_count pls_integer;
begin
/* read the input data set */
dbms_tf.get_row_set(rowset, row_count => row_count);
/* Loop through the input rows... */
for i in 1 .. row_count loop
/* ...and the defined columns, extracting the relevant value
start from 2 to skip the input string
*/
for j in 2 .. ( length(col_names) - length(replace(col_names,',')) ) + 2 loop
rowset(j).tab_varchar2(i) :=
regexp_substr(rowset(1).tab_varchar2(i), '[^,]+', 1, j - 1);
end loop;
end loop;
/* Output the new columns and their values */
dbms_tf.put_row_set(rowset);
end;
end csv_pkg;
--function
create or replace function csv_to_columns(
tab table, col_names varchar2
) return table pipelined row polymorphic using csv_pkg;
然后你只需传递:
select *
from csv_to_columns( data_clob, column_variable );
答案 1 :(得分:0)
这是一个可能的解决方案,适用于18岁以下,甚至12岁以下的Oracle版本,不确定......这不完美,并会根据您提供的数据在末尾创建一个空列 - 额外的空格,逗号等...这也可能会在“SELECT'”之间创建一个空白区域。和输出中的第一列。所有这些都可以在以后手动删除或使用更多编码。我希望这有助于,至少在某些方面:
SELECT 'SELECT '''||REPLACE(str, chr(10), ''' FROM dual'||chr(10)||'UNION ALL'||chr(10)||'SELECT ''')||''' FROM dual' str
FROM
(
SELECT TRIM(REPLACE(str, ',', ''''||', ''')) str FROM
(
SELECT TRIM(BOTH '"' FROM
'"2017-10-14,abc,1,
2019-10-13,abc,12,
2019-10-12,abc,,"') AS str FROM dual
)
)
/
这将构建可以手动或使用动态SQL清理和执行的select语句:
SELECT '2017-10-14' col, 'abc' col, '1' col, '' FROM dual
UNION ALL
SELECT '2019-10-13' col, 'abc' col, '12' col, '' FROM dual
UNION ALL
SELECT '2019-10-12' col, 'abc' col, '' col, '' FROM dual
以上select语句的输出:
COL COL_1 COL_2
2017-10-14 abc 1
2019-10-13 abc 12
2019-10-12 abc null