Sql 如何在oracle中将逗号分隔的值放入列

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

我有一个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      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?欢迎时间旅行者!;-)@大卫法伯:是的。未来是现在:)