【问题标题】:Data parsing from one column to multiple columns从一列到多列的数据解析
【发布时间】:2013-03-13 12:05:16
【问题描述】:

我有一个包含如下数据的文本文件:

A 123 JoeBSD1639973e7378790
A 344 TomGDF7393694e0902087
B 344 ZenGDF9838987e0849399

我已经使用 sqlldr 批量插入到临时表中,并且所有数据都在一个列中,因为我这里没有任何字段分隔符。

现在我想将这些数据分成如下列:

Section    Book1   Name   Book2   RollNo   Book3   RegNo
----------------------------------------------------------
A          123     Joe    BSD     1639973  e       7378790
A          344     Tom    GDF     7393694  e       0902087
B          344     Zen    GDF     9838987  e       0849399

我可以识别字段的方式是使用字符长度,例如 Section 是 2 长度,Book1 是 4,Name 是 3,Book2 是 3,RollNo 是 7,Book3 是 1,RegNo 是 7。

有人可以帮助我进行查询以进行此转换吗?

【问题讨论】:

  • 使用 substr,因为谈论的是固定长度的块 techonthenet.com/oracle/functions/substr.php
  • 这里的主要问题是前两个字段的长度:Section 和 Book1。部分是 2 个字符字段和书 4 还是书 5 和部分 1?根据数据,该部分的外观可以是 2 个字符和第 4 本书,但我们无法从提供的数据中推断出这一点是否有没有空格的示例行?
  • 你是对的部分可以是 2 个字符,但在呈现的数据集中只显示 1 个字符。同样,书 1 可以是 4,但在此示例中,它仅是 3。

标签: sql oracle plsql oracle11g plsqldeveloper


【解决方案1】:

我们还可以使用 UTL 文件从平面文件中提取数据 和 UTL 文件会将数据提取为字符串本身,所以当你知道你的长度时 可以使用SUBSTR提取正确的列值,然后插入到临时表中

declare 
     f1 UTL_FILE.FILE_TYPE;
     V_str varchar(2000);
begin
     f1 := UTL_FILE.FOPEN('Directory','File_NAME.txt','W');
     loop
         UTL_FILE.GETLINE(F1,v_str);
         v1:=substr(v_str,1,2);
         v2:=substr(v_str,3,4);
         v3:=substr(v_str,7,3);
         v4:=substr(v_str,10,3);
         v5:=substr(v_str,13,7);
         v6:=substr(v_str,20,1);
         v7:=substr(v_str,21,7);
         insert into temp values(v1,v2,v3,v4,v5,v6,v7);
    end loop;
 exception
    when no_data_found then
       dbms_output.put_line('end reached');
end;

【讨论】:

    【解决方案2】:

    SubStr() 函数就是你所需要的:http://docs.oracle.com/cd/B19306_01/server.102/b14200/functions162.htm

    您可能想考虑使用外部表而不是 SQL Loader 插入临时表,因为您可以更轻松地将 SQL 函数应用于文件数据并在读取文件期间拆分列。

    【讨论】:

      【解决方案3】:

      你可以使用 substr

      例如:

      with data as (select 'A 123 JoeBSD1639973e7378790' str from dual union all
      select 'A 344 TomGDF7393694e0902087' from dual union all
      select 'B 344 ZenGDF9838987e0849399' from dual)
      select str,
             substr(str, 1, 1) section,
             substr(str, 3, 3) book1,
             substr(str, 7, 3) name,
             substr(str, 10, 3) book2,
             substr(str, 13, 7) rollno,
             substr(str, 20, 1) book3,
             substr(str, 21, 7) regno
        from data;
      

      【讨论】:

        【解决方案4】:

        这是一个例子:

        Select trim(substr('B 344 ZenGDF9838987e0849399',1,2)) as Section, 
               trim(substr('B 344 ZenGDF9838987e0849399',3,4)) as Book1,
               trim(substr('B 344 ZenGDF9838987e0849399',7,3)) as Name,
               trim(substr('B 344 ZenGDF9838987e0849399',10,3)) as Book2,
               trim(substr('B 344 ZenGDF9838987e0849399',13,7)) as RollNo,
               trim(substr('B 344 ZenGDF9838987e0849399',20,1)) as Book2,
               trim(substr('B 344 ZenGDF9838987e0849399',21,7)) as RegionNo
        from dual
        

        我用修剪来消除空格;但也许它们是相关的?

        【讨论】:

          【解决方案5】:

          这也可能有所帮助。我有类似的问题,并在 Oracle-Base 论坛中寻求帮助。此查询由 Tim - Oracle-Base.com 的版主编写:

          SELECT REGEXP_SUBSTR(str, '[A-Z][a-z]+', 1, 1) col1,
                 REGEXP_SUBSTR(str, '[A-Z]+', 1, 2) col2,
                 REGEXP_SUBSTR(str, '[0-9]+', 1, 1) col3,
                 REGEXP_SUBSTR(str, '[a-z]+', 1, 2) col4,
                 REGEXP_SUBSTR(str, '[0-9]+', 1, 2) col5
            FROM
            (
             SELECT 'JoeBSD1639973e7378790' str FROM dual
            )
            /
          
          COL1  COL2  COL3     COL4  COL5
          -----------------------------------
          Joe   BSD   1639973   e    7378790
          

          【讨论】:

            猜你喜欢
            • 2021-06-14
            • 2017-03-28
            • 2021-08-30
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2020-05-26
            • 1970-01-01
            相关资源
            最近更新 更多