数据解析从一列到多列

时间:2013-03-13 12:05:17

标签: sql oracle plsql oracle11g plsqldeveloper

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

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

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

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

5 个答案:

答案 0 :(得分:1)

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

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

答案 1 :(得分:1)

你可以使用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;

答案 2 :(得分: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;

答案 3 :(得分:0)

以下是一个例子:

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

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

答案 4 :(得分:0)

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

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