将1字段中的值分隔为x数

时间:2016-05-02 21:47:31

标签: sql oracle

我有一个名为 multi_value 的字段,其中包含:

  

" 1700,4000,3485,9684,20394,39448"

我只需要将每个值分成一个字段,例如

multi_value1, multi_value2, multi_value3, multi_value4, multi_value5, multi_value6

需要考虑的事项:

有时,它可能只有3个值,也可能是2个值,但通常最多可以有6个值。

这些值目前由逗号分隔,如上所示。

值的大小可以从2个字符一直变化到10个。

如何使用Oracle实现这一目标?

谢谢!

2 个答案:

答案 0 :(得分:1)

Oracle安装程序

CREATE TYPE VARCHAR2_TABLE AS TABLE OF VARCHAR2(4000);
/

CREATE OR REPLACE FUNCTION split_String(
  i_str    IN  VARCHAR2,
  i_delim  IN  VARCHAR2 DEFAULT ','
) RETURN VARCHAR2_TABLE DETERMINISTIC
AS
  p_result       VARCHAR2_TABLE := VARCHAR2_TABLE();
  p_start        NUMBER(5) := 1;
  p_end          NUMBER(5);
  c_len CONSTANT NUMBER(5) := LENGTH( i_str );
  c_ld  CONSTANT NUMBER(5) := LENGTH( i_delim );
BEGIN
  IF c_len > 0 THEN
    p_end := INSTR( i_str, i_delim, p_start );
    WHILE p_end > 0 LOOP
      p_result.EXTEND;
      p_result( p_result.COUNT ) := SUBSTR( i_str, p_start, p_end - p_start );
      p_start := p_end + c_ld;
      p_end := INSTR( i_str, i_delim, p_start );
    END LOOP;
    IF p_start <= c_len + 1 THEN
      p_result.EXTEND;
      p_result( p_result.COUNT ) := SUBSTR( i_str, p_start, c_len - p_start + 1 );
    END IF;
  END IF;
  RETURN p_result;
END;
/

查询1

SELECT split_string( '1700, 4000, 3485, 9684, 20394, 39448' )
FROM   DUAL;

<强>输出

MULTI_VALUE_STRING
---------------------------------------------------------------------
TEST.VARCHAR2_TABLE('1700',' 4000',' 3485',' 9684',' 20394',' 39448')

查询2

SELECT TO_NUMBER( TRIM( COLUMN_VALUE ) ) AS value
FROM   TABLE( split_string( '1700, 4000, 3485, 9684, 20394, 39448' ) );

<强>输出

     VALUE
----------
      1700 
      4000 
      3485 
      9684 
     20394 
     39448 

查询3

WITH table_name( value ) AS (
  SELECT '1700, 4000, 3485, 9684, 20394, 39448' FROM DUAL
)
SELECT TO_NUMBER( REGEXP_SUBSTR( value, '\d+', 1,  1 ) ) AS v1,
       TO_NUMBER( REGEXP_SUBSTR( value, '\d+', 1,  2 ) ) AS v2,
       TO_NUMBER( REGEXP_SUBSTR( value, '\d+', 1,  3 ) ) AS v3,
       TO_NUMBER( REGEXP_SUBSTR( value, '\d+', 1,  4 ) ) AS v4,
       TO_NUMBER( REGEXP_SUBSTR( value, '\d+', 1,  5 ) ) AS v5,
       TO_NUMBER( REGEXP_SUBSTR( value, '\d+', 1,  6 ) ) AS v6,
       TO_NUMBER( REGEXP_SUBSTR( value, '\d+', 1,  7 ) ) AS v7,
       TO_NUMBER( REGEXP_SUBSTR( value, '\d+', 1,  8 ) ) AS v8,
       TO_NUMBER( REGEXP_SUBSTR( value, '\d+', 1,  9 ) ) AS v9,
       TO_NUMBER( REGEXP_SUBSTR( value, '\d+', 1, 10 ) ) AS v10
FROM   table_name

<强>输出

        V1         V2         V3         V4         V5         V6         V7         V8         V9        V10
---------- ---------- ---------- ---------- ---------- ---------- ---------- ---------- ---------- ----------
      1700       4000       3485       9684      20394      39448                                             

答案 1 :(得分:0)

正如我在你对你的问题的评论中提到的,分割字符串并不困难。这是它的完成方式 - 但请阅读我的评论并做出回应。

在下面的查询中,第一行只是设置测试数据;实际查询从第2行开始。

with test_data (input_str) as (select '1700, 4000, 3485, 9684, 20394, 39448' from dual)
select 'multi_value' || level as name,
       regexp_substr(input_str, '\s?(\d*)(,|$)', 1, level, null, 1) as value
from test_data
connect by level <= regexp_count(input_str, ',') + 1
   and     prior sys_guid() is not null;

<强>输出

NAME                 VALUE
----------------     -------------
multi_value1         1700
multi_value2         4000
multi_value3         3485
multi_value4         9684
multi_value5         20394
multi_value6         39448

或者 - 你的意思是这样的吗?

<强>输出

MULTI_VALUE1 MULTI_VALUE2 MULTI_VALUE3 MULTI_VALUE4 MULTI_VALUE5 MULTI_VALUE6
------------ ------------ ------------ ------------ ------------ ------------
        1700         4000         3485         9684        20394        39448
         120          300    100000000

查询以实现此结果:

with test_data (input_str) as (
            select '1700, 4000, 3485, 9684, 20394, 39448' from dual union all
            select '120, 300, 100000000' from dual)
select to_number(regexp_substr(input_str, '\s?(\d*)(,|$)', 1, 1, null, 1)) as multi_value1,
       to_number(regexp_substr(input_str, '\s?(\d*)(,|$)', 1, 2, null, 1)) as multi_value2,
       to_number(regexp_substr(input_str, '\s?(\d*)(,|$)', 1, 3, null, 1)) as multi_value3,
       to_number(regexp_substr(input_str, '\s?(\d*)(,|$)', 1, 4, null, 1)) as multi_value4,
       to_number(regexp_substr(input_str, '\s?(\d*)(,|$)', 1, 5, null, 1)) as multi_value5,
       to_number(regexp_substr(input_str, '\s?(\d*)(,|$)', 1, 6, null, 1)) as multi_value6
from test_data;