【问题标题】:SQL string manipulation to return multiple rowsSQL 字符串操作以返回多行
【发布时间】:2010-05-07 02:06:22
【问题描述】:

我是一位经验丰富的程序员,但对 SQL 比较陌生。我们正在使用 Oracle 10 和 11。我有一个使用 SQL 的系统,该系统将实际行与虚拟行(例如“SELECT 1 from DUAL”)根据需要进行联合和相交,这一切似乎都有效。

我的问题是我需要将这个需要数据行的系统与新数据结合起来,新数据将包含(为了简化起见)逗号分隔字符串中的数据。

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

还有第二个问题,但我会单独问。但我怀疑如果可能的话,如果上述解决方案可以用作另一个 SQL 语句中的表(即,与我现有的系统一起使用),它会简化事情。感谢您的帮助。

【问题讨论】:

  • 虽然可以做到,但这不是 SQL 的用途。使用高级脚本语言对格式化数据进行预处理并在执行查询后将其混合或将其插入单独的表中会更加简洁。

标签: sql oracle oracle10g oracle11g


【解决方案1】:

它看起来很丑,但它确实有效:

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;

房车 = = 1 5 2 6 3 7a 4 8b 5 6 鲍勃

【讨论】:

    【解决方案2】:

    您真的应该将该逗号分隔的字符串提取到任何语言的外部程序中,将其拆分,将其批量加载到临时表中,然后在查询中使用该临时表。

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

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

    【讨论】:

      【解决方案3】:

      对于 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
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2018-08-08
        • 1970-01-01
        • 1970-01-01
        • 2016-06-13
        • 1970-01-01
        相关资源
        最近更新 更多