我需要导入这种格式的文件:
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 vs. 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 :(得分:1)
您的初步方法可能会遇到问题,因为
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
中的ID:
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