sql - 带有两个行终止符的 BULK INSERT

标签 sql sql-server tsql bulkinsert bcp

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

'Hello Mom,

we meet again'

应该给出 5 条记录:

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

我尝试通过 ROWTERMINATOR = ' 'BULK INSERT 来完成此操作,但是将 new line 视为 terminator 也是,我在其中一个结果中得到了 'Mom,we'

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

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

最佳答案

给定:

The file cannot be preprocessed outside of 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');
    
  • 如果您没有使用(或不能使用)格式文件,请务必使用正确的“SINGLE_”选项,因为您可以执行 SINGLE_CLOB(返回 VARCHAR (MAX) 对于标准 ASCII 文件)或 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 任务。

关于sql - 带有两个行终止符的 BULK INSERT,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27730419/

相关文章:

sql - 文件中的日期格式转换 'YYYYMMDD' TO 'MM/DD/YYYY'

sql - DateDiff Access 查询返回 #Error

sql - 将sql server连接设置为只读?

sql - 返回连续日期的临时表

sql-server - T-SQL 插入或更新

sql - 存储过程使用游标返回多个查询结果

mysql - 计数中的最小值

.net - Crystal Reports 2008 和 .mdf 文件有哪些先决条件

层次结构中的 SQL Top 父记录

sql-server - 如何使用 tsql 更新具有增量值的列?