Sql 如何在oracle中将逗号分隔的值放入列
我有一个JSON响应,在处理响应后,我的输出如下所示:Sql 如何在oracle中将逗号分隔的值放入列,sql,json,oracle,plsql,Sql,Json,Oracle,Plsql,我有一个JSON响应,在处理响应后,我的输出如下所示: column_variable := 'col1,col2,col3'; data_clob := "2017-10-14,abc,1, 2019-10-13,abc,12, 2019-10-12,abc,, " ; col1 col2 col3 2017-10-14 abc 1 2019-10-13 abc 12 2019-10-12 abc
column_variable := 'col1,col2,col3';
data_clob :=
"2017-10-14,abc,1,
2019-10-13,abc,12,
2019-10-12,abc,,
"
;
col1 col2 col3
2017-10-14 abc 1
2019-10-13 abc 12
2019-10-12 abc null
由于原始响应具有新行
的转义字符,数据\u clob
也相应地进行了转换
如何在oracle表中转换此逗号分隔的值:
我的输出应该如下所示:
column_variable := 'col1,col2,col3';
data_clob :=
"2017-10-14,abc,1,
2019-10-13,abc,12,
2019-10-12,abc,,
"
;
col1 col2 col3
2017-10-14 abc 1
2019-10-13 abc 12
2019-10-12 abc null
我在浏览类似的问题,但我不想使用REGEXP\u SUBSTR
,因为我不知道我在回答中会得到多少列。
例如:列_变量
可能有'col1、col2、col3、col4、col5、col6'
我正在使用oracle 12.1.0.2.0
请帮忙 使用多态表函数(Oracle 18c)有一种非常简单的方法来实现它: : 和机构:
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 );
这里有一个可能的解决方案,适用于18到12岁以下的Oracle版本,不确定。。。这并不完美,将根据您提供的数据在末尾创建一个空列-额外的空格、逗号等。。。这也可能在“选择”和输出中的第一列之间创建空白。所有这些都可以在以后手动或通过更多编码删除。我希望这至少在某些方面有所帮助:
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
)
)
/
这将生成select语句,可以手动或使用动态SQL清理和执行该语句:
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
您能否在问题中显示原始的JSON响应?也许直接从JSON解析数据会更容易?嗨,Krokodilko..刚刚添加了原始的JSON响应。这个JSON有一个糟糕的结构,如果它看起来像这样会更好更容易:
data:[{“col1”:“2017-10-14”,“col2”:“abc”,“col3”:1},{“col1”:“2019-10-13”,“col2”:“abc”,“col3”:12},{“col1”:“2019-10-12”,“col2”:“abc”}]
。也许这个API的作者可以更改响应的格式?是的,我同意它的结构不好,但我无法控制更改它。因此,您希望我们只需编写一个查询/过程来神奇地转换您的数据,并为您提供一个数据库表
,而之前对数据类型一无所知,表格将包含的列数等?您好,谢谢您的回答!您知道oracle 12.1.0.2是否提供了类似的功能。0@joe也许你需要编写一个自定义的。Oracle 18c?欢迎时间旅行者!;-)@大卫法伯:是的。未来是现在:)