SQL字符串操作返回多行

时间:2010-05-07 02:06:23

标签: sql oracle oracle10g oracle11g

我是一名经验丰富的程序员,但对SQL来说相对较新。我们正在使用Oracle 10和11.我有一个使用SQL的系统,它将实际行与虚拟行(例如“SELECT 1来自DUAL”)结合起来,根据需要进行联合和交叉,这些似乎都有效。

我的问题是我需要将这个期望数据行的系统与新数据相结合,这些数据将包含数据(简单来说就是简化)逗号分隔的字符串。

所以我认为我需要的是一种方法,将字符串转换为:“5,6,7,8”为4行,每行一列,第一行为“5”,第二行为“6”在其他语言中,我用逗号作为分隔符进行“拆分”。当然,数据并不总是有4个条目。

还有第二个问题,但我会另外提问。但我怀疑如果可能的话,如果上面的解决方案可以用作另一个SQL语句中的表(即,使用我现有的系统),它将简化一些事情。谢谢你的帮助。

3 个答案:

答案 0 :(得分:2)

它看起来很难看,但它有效:

select r
      ,substr(','||csv||',',
              instr(','||csv||',',',',1,r)+1,
              instr(','||csv||',',',',1,r+1)-instr(','||csv||',',',',1,r)-1) v
from   (select '5,6,7a,8b,,bob' csv from dual)
      ,(select rownum r from dual connect by level <= 4000)
where  instr(csv||',',',',1,r) > 0;

R   V
=   =
1   5
2   6
3   7a
4   8b
5
6   bob

答案 1 :(得分:1)

您应该将该逗号分隔的字符串解压缩为任何语言的外部程序,将其拆分,将其批量加载到临时表中,并在查询中使用该临时表。

如果您绝对必须在SQL中执行此操作,本文将向您介绍如何执行此操作:

http://www.oracle.com/technology/oramag/code/tips2007/070907.html

答案 2 :(得分:1)

对于SQL使用,您可以执行以下操作...

CREATE OR REPLACE TYPE tab_varchar2 AS TABLE OF VARCHAR2( 4000 );
/

CREATE OR REPLACE FUNCTION string_to_rows
   ( pv_string   IN   VARCHAR2
   , pv_delimiter   IN   VARCHAR2   DEFAULT   '_'
   )
   RETURN tab_varchar2
   PIPELINED
AS
   lv_string   VARCHAR2( 32767 )   DEFAULT   pv_string || pv_delimiter;
   lv_num   PLS_INTEGER;
BEGIN
   LOOP
      lv_num := INSTR( lv_string, pv_delimiter );
      EXIT WHEN ( NVL( lv_num, 0 ) = 0 );

      PIPE ROW( LTRIM( RTRIM( SUBSTR( lv_string, 1, lv_num - 1 ) ) ) );

      lv_string := LTRIM( SUBSTR( lv_string, lv_num + 1 ) );

    END LOOP;

    RETURN;
END;
/

然后你可以运行这样的东西......

SELECT c.owner, c.table_name, c.column_name, c.data_type
     , t.column_value   column_token
  FROM dba_tab_columns c
     , TABLE( string_to_rows( c.column_name ) ) t
 WHERE c.owner = 'SYS'
   AND c.table_name = 'DBA_INDEXES'
   AND c.column_name = 'AVG_LEAF_BLOCKS_PER_KEY'

哪会归还......

Row# OWNER TABLE_NAME  COLUMN_NAME             DATA_TYPE COLUMN_TOKEN
---- ----- ----------- ----------------------- --------- ------------
1    SYS   DBA_INDEXES AVG_LEAF_BLOCKS_PER_KEY NUMBER    AVG
2    SYS   DBA_INDEXES AVG_LEAF_BLOCKS_PER_KEY NUMBER    LEAF
3    SYS   DBA_INDEXES AVG_LEAF_BLOCKS_PER_KEY NUMBER    BLOCKS
4    SYS   DBA_INDEXES AVG_LEAF_BLOCKS_PER_KEY NUMBER    PER
5    SYS   DBA_INDEXES AVG_LEAF_BLOCKS_PER_KEY NUMBER    KEY