固定宽度的进口具有取决于线

问题描述:

的第一个字符场宽度我需要导入这种格式的文件:固定宽度的进口具有取决于线

PParent line  has some fields   with fixed width 
CChild line of Parent  Has fixed width with different widths than Parent 
CAnother Child   Fixed width consistent with Child-lines but not Parent 
PSecond Parent has more fields   again fixed width like other Parents 
CThird Child    This time belong to 2nd Parent as that's the preceding P-line 

因此,与被固定的列是依赖于第一字符的宽度作为P对C.我没有想出这个文件格式,但我需要处理它的吸盘...我目前正在读它,像这样(简化):

create table #fixed (
    line varchar(max) 
) 
create table #link (
    id int identity, 
    parent int, 
    linetype char, 
    line varchar(max) 
) 

bulk insert #fixed from '\\unc\path\to\file.txt' 
with (
    fieldterminator = '' 
) 

insert into #link(linetype, line) 
select substring(line, 1, 1), line 
from #fixed 

update c set 
    c.parent = p.id 
from #link c 
cross apply (
    select top 1 id from #link 
    where linetype = 'P' and id < c.id 
    order by id desc 
) p 
where c.linetype = 'C' 

这可行,但我不喜欢它,我特别关心SQL Server插入到#link以任意顺序排列,因此在update中丢失了正确的亲子关系,特别是对于比这5行更大的文件。

但我没有看到在这里强制执行order的方法,或者使用使用格式文件的bulk insert导入此固定宽度与变化宽度格式。

编辑:一种方式我看到的是读取该文件与openrowset(bulk '\\unc\file.txt', single_clob)和手动提取的线条。主要是我现在的问题是,我是否应该担心insert into #link的这个顺序,以保证转换为single_clob

+0

您是否能够使用像SSIS这样的技术?您可以读取您的平面文件,并在读取每行时为其分配一个连续的行号。 – Greenspark 2014-11-04 16:57:11

+0

我仅限于这样做,它是一块T-SQL,可以在文件存储和运行时进行存储和运行通过另一个进程在文件夹中检测到。 – funkwurm 2014-11-05 00:48:02

您最初的做法是命中的几率问题,因为

insert into #link(linetype, line) 
select substring(line, 1, 1), line 
from #fixed 

没有ORDER BY条款;不能保证行将被插入#link的顺序将反映它们在源文件中的顺序。

一种方法是将一个标识列添加到#fixed

CREATE TABLE #fixed (
    id INT IDENTITY, 
    line VARCHAR(MAX) 
) 

因为BULK INSERT将在它们出现在源文件中的命令行添加到目标表中。

这意味着您需要使用格式文件来启用BULK INSERT以跳过IDENTITY列。

格式文件需要有内容类似:

9.0 
1 
1 SQLCHAR 0 99999 "\r\n" 2 line SQL_Latin1_General_CP1_CI_AS 

然后它可以与像

BULK INSERT #fixed FROM '\\unc\path\to\file.txt' 
WITH (
    FIELDTERMINATOR = '', 
    FORMATFILE = 'c:\temp\test.fmt' 
) 

(假设您保存格式文件到c命令使用: \ temp \ test.fmt)

然后,您可以使用已有的代码进行小修改以使用来自#fixed的编号:

create table #link (
    id int , 
    parent int, 
    linetype char, 
    line varchar(max) 
) 

insert into #link(id, linetype, line) 
select id, substring(line, 1, 1), line 
from #fixed 
order by id 
+0

啊,我可以用格式文件告诉'bulk insert'跳过列,太棒了!我实际上调整了你的格式文件,让它直接插入'#link'并跳过'id'和'parent'。这样我就可以马上得到我的'linetype'值。非常感谢。 – funkwurm 2014-11-05 16:28:55