【问题标题】:BULK INSERT with two row terminators带有两个行终止符的 BULK INSERT
【发布时间】:2015-02-28 02:12:25
【问题描述】:

我正在尝试导入一个文本文件,因此结果将只是一列的单独行中的单词。 例如一段文字:

'你好,妈妈,

我们又见面了'

应该给出5条记录:

'Hello' 
'Mom,'
'we' 
'meet' 
'again'

我尝试使用BULK INSERTROWTERMINATOR = ' ' 来完成此操作,但是将new line 也视为terminator 也存在问题,我在其中一个结果中得到'Mom,we'

据我所知,没有办法将second ROWTEMRMINATOR 添加到BULK INSERT(真的吗?)。 您知道实现上述结果的最佳方法是什么?

该文件不能在 SQL Server 之外进行预处理,并且该方法应该对数百个包含 thausands 行单词的文件很有用,这些文件在不同的时间导入,而不仅仅是一次。

【问题讨论】:

  • 我认为使用BULK INSERT 进行这个单词解析任务并不是最好的选择。
  • 有很多方法可以“重新格式化”文件,以便批量插入以在源计算机上工作。使用其中一种工具来处理数据。尝试使用 BULK INSERT 是错误的。
  • 你能预处理文件吗?几行 C# 就足以完成这项工作。
  • 感谢您的 cmets。我添加了一些细节来澄清。我知道 BULK INSERT 不是最好的选择,问题是什么? ;)
  • 尊敬的 usr,我之前在问题中添加了详细信息;)“无法在 SQL Server 之外对文件进行预处理”

标签: sql sql-server tsql bulkinsert bcp


【解决方案1】:

给定:

无法在 SQL Server 之外对文件进行预处理

选项 1

为什么不使用OPENROWSET(BULK...)?这将允许您导入/插入(处理行终止符),同时拆分(处理字段终止符)。根据您是否可以创建 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;

注意事项:

  • 对于这两种方法,您都需要使用字符串拆分器。基于 SQLCLR 的拆分器是最快的,在上面的示例中,我使用了 SQL# 库中的一个(我创建了它,但免费版本中提供了 String_Split 函数)。你也可以自己写。如果您自己编写并且使用格式文件,则允许多个拆分字符可能是个好主意,这样您就可以同时传入“”和“\n”并摆脱REPLACE()

  • 如果您可以编写自己的 SQLCLR 字符串拆分器,那么最好只编写一个接受 @FilePath 的输入参数的 SQLCLR 存储过程,读取文件,进行拆分,然后将单词输出为单列的多行:

    INSERT INTO dbo.TableName(ColumnName)
      EXEC dbo.MySQLCLRproc(N'C:\path\to\file.txt');
    
  • 1234563 SINGLE_NCLOB(对于 Unicode 文件返回 NVARCHAR(MAX))。
  • 即使您可以创建格式文件,可能将整个文件作为单个字符串拉入会更有效,具体取决于文件的大小,因为拆分一个大文件string 可以相当快地完成,并且将是单个函数调用,而包含数千个短行的文件将包含数千个函数调用,这些函数调用也很快,但可能不会比单个调用快 1000 倍。但如果文件为 1 MB 或更大,那么我可能仍会选择执行格式化文件并处理尽可能多的短行。

选项 2

如果您所说的“预处理”是指已更改,但对于简单地读取它们并从 SQL Server 外部的东西插入数据没有限制,您应该编写一个小型 .NET 应用程序来读取行,拆分行,并通过调用接受表值参数 (TVP) 的存储过程来插入数据。我在 S.O. 的另一个答案中详细介绍了这种方法:

How can I insert 10 million records in the shortest time possible?

这可以编译为控制台应用程序并在批处理(即 .CMD / .BAT)脚本中使用,甚至可以安排为 Windows 任务。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-07-15
    • 1970-01-01
    • 2019-02-20
    • 1970-01-01
    • 2012-06-06
    • 1970-01-01
    • 2013-12-05
    • 1970-01-01
    相关资源
    最近更新 更多