带有两个行终止符的 BULK INSERT
BULK INSERT with two row terminators
我正在尝试导入一个文本文件,因此结果将只是一列单独行中的单词。
例如文本:
'Hello Mom,
we meet again'
应给出 5 条记录:
'Hello'
'Mom,'
'we'
'meet'
'again'
我试着用 BULK INSERT
和 ROWTERMINATOR = ' '
来完成这个,但是把 new line
当作 terminator
也有问题,我得到 'Mom,we'
在其中一个结果中。
据我所知,无法将 second ROWTEMRMINATOR
添加到 BULK INSERT
(是吗?)。
您知道实现上述结果的最佳方法是什么?
无法在 SQL 服务器外对文件进行预处理,并且该方法应该适用于数百个包含 thausands 行单词的文件,在不同时间导入,而不仅仅是一次。
给定:
The file cannot be preprocessed outside of SQL Server
选项 1
为什么不使用 OPENROWSET(BULK...)? This would allow you to import/insert (which takes care of the row terminator) while at the same time splitting (which takes care of the field terminator). Depending on whether or not you can create a Format File,它应该类似于以下之一:
格式化文件 = 拆分每一行
INSERT INTO dbo.TableName (ColumnName)
SELECT split.SplitVal
FROM OPENROWSET(BULK 'path\to\file.txt',
FORMATFILE='Path\to\FormatFile.XML') data(eachrows)
CROSS APPLY SQL#.String_Split(data.eachrow, N' ', 2) split;
无格式文件 = 将整个文件拆分为一行
INSERT INTO dbo.TableName (ColumnName)
SELECT split.SplitVal
FROM OPENROWSET(BULK 'path\to\file.txt', SINGLE_CLOB) data(allrows)
CROSS APPLY SQL#.String_Split(
REPLACE(data.allrows, NCHAR(10), N' '),
N' ',
2 -- remove empty entries
) split;
备注:
对于这两种方法,您都需要使用字符串拆分器。 SQL 基于 CLR 的拆分器是最快的,在上面的示例中,我使用了 SQL# 库中的一个(我创建了该库,但 String_Split
函数在免费版本中可用)。你也可以自己写。如果您自己编写并且 不 使用格式文件,允许多个拆分字符可能是个好主意,这样您就可以同时传入 " " 和 "\n" 和摆脱 REPLACE()
.
如果您可以编写自己的 SQLCLR 字符串拆分器,那么只编写一个接受输入参数的 SQLCLR 存储过程可能会更好@FilePath
,读取文件,拆分,吐出单列多行的单词:
INSERT INTO dbo.TableName(ColumnName)
EXEC dbo.MySQLCLRproc(N'C:\path\to\file.txt');
如果您没有使用(或不能使用)格式文件,请务必使用正确的 "SINGLE_" 选项,因为您可以使用 SINGLE_CLOB
(returns VARCHAR(MAX)
用于标准 ASCII 文件)或 SINGLE_NCLOB
(returns NVARCHAR(MAX)
用于 Unicode 文件)。
即使您可以创建格式文件,可能将整个文件作为单个字符串拉入会更有效,具体取决于文件的大小文件,因为拆分一个大字符串可以相当快地完成并且将是一个函数调用,而一个包含数千个短行的文件将是数千个函数调用,这些函数调用也很快,但可能不会比单个调用快 1000 倍.但是如果文件是 1 MB 或更大,那么我可能仍然会选择格式化文件并处理尽可能多的短行。
选项 2
如果 "pre-processed" 你的意思是改变了,但是没有限制简单地读取它们并将数据从外部的东西插入 SQL 服务器,你应该写一个小的.NET应用程序,它通过调用接受 Table 值参数 (TVP) 的存储过程读取行、拆分行并插入数据。我在 S.O.:
的另一个答案中详细介绍了这种方法
How can I insert 10 million records in the shortest time possible?
这可以编译为控制台应用程序并用于批处理(即 .CMD / .BAT)脚本,甚至安排为一个 Windows 任务。
我正在尝试导入一个文本文件,因此结果将只是一列单独行中的单词。 例如文本:
'Hello Mom,
we meet again'
应给出 5 条记录:
'Hello'
'Mom,'
'we'
'meet'
'again'
我试着用 BULK INSERT
和 ROWTERMINATOR = ' '
来完成这个,但是把 new line
当作 terminator
也有问题,我得到 'Mom,we'
在其中一个结果中。
据我所知,无法将 second ROWTEMRMINATOR
添加到 BULK INSERT
(是吗?)。
您知道实现上述结果的最佳方法是什么?
无法在 SQL 服务器外对文件进行预处理,并且该方法应该适用于数百个包含 thausands 行单词的文件,在不同时间导入,而不仅仅是一次。
给定:
The file cannot be preprocessed outside of SQL Server
选项 1
为什么不使用 OPENROWSET(BULK...)? This would allow you to import/insert (which takes care of the row terminator) while at the same time splitting (which takes care of the field terminator). Depending on whether or not you can create a Format File,它应该类似于以下之一:
格式化文件 = 拆分每一行
INSERT INTO dbo.TableName (ColumnName)
SELECT split.SplitVal
FROM OPENROWSET(BULK 'path\to\file.txt',
FORMATFILE='Path\to\FormatFile.XML') data(eachrows)
CROSS APPLY SQL#.String_Split(data.eachrow, N' ', 2) split;
无格式文件 = 将整个文件拆分为一行
INSERT INTO dbo.TableName (ColumnName)
SELECT split.SplitVal
FROM OPENROWSET(BULK 'path\to\file.txt', SINGLE_CLOB) data(allrows)
CROSS APPLY SQL#.String_Split(
REPLACE(data.allrows, NCHAR(10), N' '),
N' ',
2 -- remove empty entries
) split;
备注:
对于这两种方法,您都需要使用字符串拆分器。 SQL 基于 CLR 的拆分器是最快的,在上面的示例中,我使用了 SQL# 库中的一个(我创建了该库,但
String_Split
函数在免费版本中可用)。你也可以自己写。如果您自己编写并且 不 使用格式文件,允许多个拆分字符可能是个好主意,这样您就可以同时传入 " " 和 "\n" 和摆脱REPLACE()
.如果您可以编写自己的 SQLCLR 字符串拆分器,那么只编写一个接受输入参数的 SQLCLR 存储过程可能会更好
@FilePath
,读取文件,拆分,吐出单列多行的单词:INSERT INTO dbo.TableName(ColumnName) EXEC dbo.MySQLCLRproc(N'C:\path\to\file.txt');
如果您没有使用(或不能使用)格式文件,请务必使用正确的 "SINGLE_" 选项,因为您可以使用
SINGLE_CLOB
(returnsVARCHAR(MAX)
用于标准 ASCII 文件)或SINGLE_NCLOB
(returnsNVARCHAR(MAX)
用于 Unicode 文件)。即使您可以创建格式文件,可能将整个文件作为单个字符串拉入会更有效,具体取决于文件的大小文件,因为拆分一个大字符串可以相当快地完成并且将是一个函数调用,而一个包含数千个短行的文件将是数千个函数调用,这些函数调用也很快,但可能不会比单个调用快 1000 倍.但是如果文件是 1 MB 或更大,那么我可能仍然会选择格式化文件并处理尽可能多的短行。
选项 2
如果 "pre-processed" 你的意思是改变了,但是没有限制简单地读取它们并将数据从外部的东西插入 SQL 服务器,你应该写一个小的.NET应用程序,它通过调用接受 Table 值参数 (TVP) 的存储过程读取行、拆分行并插入数据。我在 S.O.:
的另一个答案中详细介绍了这种方法How can I insert 10 million records in the shortest time possible?
这可以编译为控制台应用程序并用于批处理(即 .CMD / .BAT)脚本,甚至安排为一个 Windows 任务。