10

我似乎无法弄清楚这是怎么回事。

下面是我尝试批量插入 SQL Server 2005 的文件示例:

***A NICE HEADER HERE***
0000001234|SSNV|00013893-03JUN09
0000005678|ABCD|00013893-03JUN09
0000009112|0000|00013893-03JUN09
0000009112|0000|00013893-03JUN09

这是我的批量插入语句:

BULK INSERT sometable
FROM 'E:\filefromabove.txt
WITH
(
FIRSTROW = 2,
FIELDTERMINATOR= '|',
ROWTERMINATOR = '\n'
)

但是,由于某种原因,我能得到的唯一输出是:

0000005678|ABCD|00013893-03JUN09
0000009112|0000|00013893-03JUN09
0000009112|0000|00013893-03JUN09

第一条记录总是被跳过,除非我完全删除标题并且不使用 FIRSTROW 参数。这怎么可能?

提前致谢!

4

6 回答 6

16

我认为您不能使用BULK INSERT/跳过不同格式的行BCP

当我运行这个:

TRUNCATE TABLE so1029384

BULK INSERT so1029384
FROM 'C:\Data\test\so1029384.txt'
WITH
(
--FIRSTROW = 2,
FIELDTERMINATOR= '|',
ROWTERMINATOR = '\n'
)

SELECT * FROM so1029384

我得到:

col1                                               col2                                               col3
-------------------------------------------------- -------------------------------------------------- --------------------------------------------------
***A NICE HEADER HERE***
0000001234               SSNV                                               00013893-03JUN09
0000005678                                         ABCD                                               00013893-03JUN09
0000009112                                         0000                                               00013893-03JUN09
0000009112                                         0000                                               00013893-03JUN09

看起来它需要'|' 即使在标题数据中,因为它会读取到第一列 - 将换行符吞入第一列。显然,如果您包含一个字段终止符参数,它希望每一行都必须有一个。

您可以使用预处理步骤剥离该行。另一种可能性是只选择完整的行,然后处理它们(不包括标题)。或者使用可以处理这个问题的工具,比如 SSIS。

于 2009-06-22T21:19:06.017 回答
9

也许检查标题是否与实际数据行具有相同的行尾(如 中所指定ROWTERMINATOR)?

更新:来自MSDN

FIRSTROW 属性不打算跳过列标题。BULK INSERT 语句不支持跳过标头。跳过行时,SQL Server 数据库引擎仅查看字段终止符,而不验证跳过行的字段中的数据。

于 2009-06-22T21:11:35.580 回答
6

我发现将整行读入一列然后使用 XML 解析数据是最简单的。

IF (OBJECT_ID('tempdb..#data') IS NOT NULL) DROP TABLE #data
CREATE TABLE #data (data VARCHAR(MAX))

BULK INSERT #data FROM 'E:\filefromabove.txt' WITH (FIRSTROW = 2, ROWTERMINATOR = '\n')

IF (OBJECT_ID('tempdb..#dataXml') IS NOT NULL) DROP TABLE #dataXml
CREATE TABLE #dataXml (ID INT NOT NULL IDENTITY(1,1) PRIMARY KEY CLUSTERED, data XML)

INSERT #dataXml (data)
SELECT CAST('<r><d>' + REPLACE(data, '|', '</d><d>') + '</d></r>' AS XML)
FROM #data

SELECT  d.data.value('(/r//d)[1]', 'varchar(max)') AS col1,
        d.data.value('(/r//d)[2]', 'varchar(max)') AS col2,
        d.data.value('(/r//d)[3]', 'varchar(max)') AS col3
FROM #dataXml d
于 2013-08-07T20:12:08.280 回答
0

You can use the below snippet

BULK INSERT TextData
FROM 'E:\filefromabove.txt'
WITH
(
FIRSTROW = 2,
FIELDTERMINATOR = '|',  --CSV field delimiter
ROWTERMINATOR = '\n',   --Use to shift the control to next row
ERRORFILE = 'E:\ErrorRows.csv',
TABLOCK
)
于 2019-01-25T10:53:45.307 回答
0

让 SQL 处理引号转义和其他所有操作

BULK INSERT Test_CSV
FROM  'C:\MyCSV.csv' 
WITH (
 FORMAT='CSV'
 --FIRSTROW = 2,  --uncomment this if your CSV contains header, so start parsing at line 2
);

关于其他答案,这里也是有价值的信息:

我一直在所有答案中看到这一点:ROWTERMINATOR = '\n'
意味着\nLF,它是 Linux 风格的 EOL

在 Windows 中,EOL 由 2 个字符 CRLF 组成,因此您需要ROWTERMINATOR = '\r\n'

在此处输入图像描述

在此处输入图像描述

于 2020-11-20T03:24:24.260 回答
-1

考虑到在从非 SQL 数据源将 BCP 导入 SQL Server 后,某些数据会受到多大的破坏,我建议先将所有 BCP 导入到一些暂存表中。

例如

截断表 Address_Import_tbl

批量插入 dbo.Address_Import_tbl FROM 'E:\external\SomeDataSource\Address.csv' WITH ( FIELDTERMINATOR = '|', ROWTERMINATOR = '\n', MAXERRORS = 10 )

确保 Address_Import_tbl 中的所有列都是 nvarchar(),以使其尽可能不可知,并避免类型转换错误。

然后对 Address_Import_tbl 应用您需要的任何修复。就像删除不需要的标题一样。

然后运行 ​​INSERT SELECT 查询,从 Address_Import_tbl 复制到 Address_tbl,以及您需要的任何数据类型转换。例如,将导入的日期转换为 SQL DATETIME。

于 2014-02-06T16:43:45.110 回答