我有一个从燃油供应商门户网站下载的CSV文件。数据以分号分隔,在具有字段标题的行之前有11行注释。
有3行摘要,并且是Unix LF编码
我使用SQL命令BULK INSERT从另一个供应商处导入另一个数据文件:-
BULK INSERT [dbo].[fuel_stagingShell]
FROM '\\server\path\dataimports\fueldata\Shell\results.csv'
WITH
(
FORMAT = 'CSV',
FIELDQUOTE ='"',
FIRSTROW=2,
FIELDTERMINATOR = ',',
ROWTERMINATOR='\n',
TABLOCK
)
这很完美,因为它可以瞬间导入文件。
但是,当我尝试批量插入时,该文件将无法使用。是的,我可以通过更改FIRSTROW来跳过标题行,但是文件末尾存在三行的问题。 BULK INSERT命令上的LASTROW参数需要一个行号,由于文件的长度可变,我不知道该行号。
我当时想用C#导入文件,跳过第11行中的第1行,直到到达以“ Total;”开头的行时终止。并根据标题名称匹配列。
有没有一种方法可以导入数据行,并将其拆分为数组/ POCO /其他东西,如果您知道数据的可用性,那真的是一种简单明了的方法吗?
我还从供应商那里获得了另一个文件,该文件的格式相同,只是缺少六个字段。这就是为什么我一直认为通过匹配列名来进行填充,但是我知道填充每一行中的每个属性可能比其他未知方法慢很多。
编辑:我复制了该问题,以便可以编辑该帖子,并遇到与文件相关的错误,并且此人得到的错误消息为("IID_IColumnsInfo") error with SQL Server BULK INSERT of CSV file,所以我如注释中的@steve所示,将\ n替换为0x0a并添加了一个任意的LASTROW参数,当我注释掉FIELDQUOTE参数时,它导入了一行行。
我现在正在考虑可以预先准备文件并计算有多少行,然后从我的应用程序将其构建到动态SQL中。或者,用更长的varchar字段修改我的登台表,该字段将接受文件末尾的所有注释位,并在T-SQL存储过程中忽略它们,以验证数据并将其转换为事务表。
这是我使用的T-SQL:
BULK INSERT [dbo].[fuel_stagingDkv]
FROM '\\server\path\dataimports\fueldata\DKV\Results.csv'
WITH
(
FORMAT = 'CSV',
--FIELDQUOTE ='',
FIRSTROW=12,
LASTROW=5000,
FIELDTERMINATOR = ';',
ROWTERMINATOR='0x0a',
TABLOCK
)
答案 0 :(得分:0)
如果您知道需要在底部跳过一定数量的文件,并且可以启用xp_cmdshell
来获取文件的行数,则可以执行以下操作:
USE tempdb
GO
DECLARE
@filePath nvarchar(max) = '\\server\path\dataimports\fueldata\DKV\Results.csv'
DECLARE
@cmd nvarchar(1000) = 'type "' + @filePath + '" | find /c /v ""'
,@lastRow int
DECLARE @Output TABLE (
Id int IDENTITY(1, 1)
,CmdOutput nvarchar(300)
)
INSERT INTO @Output ( CmdOutput )
EXEC xp_cmdshell @cmd
SELECT TOP 1 @lastRow = CmdOutput
FROM @Output
WHERE
CmdOutput IS NOT NULL
ORDER BY
Id DESC
BULK INSERT [dbo].[fuel_stagingDkv]
FROM '\\server\path\dataimports\fueldata\DKV\Results.csv'
WITH
(
FORMAT = 'CSV',
--FIELDQUOTE ='',
FIRSTROW=12,
LASTROW=@lastRow,
FIELDTERMINATOR = ';',
ROWTERMINATOR='0x0a',
TABLOCK
)
或者,您也许可以使用xp_cmdshell
创建不带第一行和最后一行的新文件。