导入平面文件包含多行字段在SSIS



我想在SSIS中导入一个平面文件*.csv。但是其中一个字段是多行文本。我没有特殊的记录分隔符(也没有办法得到一个),因此是回车回车rn或CRLF。

问题是:当SSIS在多行字段中遇到CRLF时,他会传递到下一行,而不是继续作为多行字段。

这是标题和一些第一行:

"name", "firstname", "description", "age"
"John", "Smith", "blablablablablabla", 25
"Fred", "Gordon", "blablabla
blablablabla", 33
"Bill", "Buffalo", "bllllllllllllaaaaaaa
blaaaaaaa
blaalalalaaaaaaaaaa", 44

上面的例子包含1个头和3条记录。当然,SSIS将其理解为1个报头和6条记录,然后得到错误。

我不知道如何处理那个问题。

希望你能帮助我。

根据您的示例,Description字段值可以包含多个回车,这会导致创建新行。

下面的记录出现在多行…

"Bill", "Buffalo", "bllllllllllllaaaaaaa 
blaaaaaaa
blaalalalaaaaaaaaaa", 44

应该如下所示,这样SSIS才能看到预期的列数。

"Bill", "Buffalo", "bllllllllllllaaaaaaa blaaaaaaa blaalalalaaaaaaaaaa", 44

有两种方法可以解决格式问题。

  1. 如果可能的话,最简单的方法是跟踪创建文件的人,并让他们正确地完成。例如,假设他们使用的是SQL Server,那么他们可以在他们的TSQL语句中应用下面的描述字段,将回车替换为空白。(Oracle也有类似的功能)

    REPLACE(Description, CHAR(13),' ')

如果需要替换换行,则使用CHAR(10)。

  • 否则,我知道联系文件的来源并不总是可能的。在这种情况下,您可以在将文本文件输入SSIS之前以编程方式修改它。下面的链接讨论了如何应用Excel来做到这一点,你可以保存到一个新的csv文件,然后通过SSIS导入。
  • http://www.mrexcel.com/forum/excel-questions/304939-importing-text-data-carriage-returns-into-excel.html

    如果您正在考虑在作业中设置SSIS包,那么您可以在控制流的早期部分编写脚本任务,它将做同样的事情并绕过Excel。链接中提供的VB代码可以很容易地适应脚本任务。

    考虑到无法联系文本文件的源,并且每个csv中的列数会有所不同,执行导入的最佳选择是继续执行答案#1的选项2的变体。这将需要在控制流中进行一些定制和应用脚本任务。

    • 在运行SSIS包的服务器上,创建一个存放临时文本文件的桶文件夹。每次处理CSV文件时,将从中创建一个名为"destFile.csv"的临时文件,这就是您要导入的文件。每次脚本任务处理不同的csv文件时,它将保存到这个临时文件和位置。
    • 在SSIS包中创建两个变量。一个用于源文件,第二个用于目标文件。
    • 创建一个脚本任务,并定义发送给它的两个变量。
    • 将以下c#添加到脚本任务中,并记住在顶部替换源文件和目标文件的赋值。它们应该设置为刚刚创建的新用户变量。

      <>之前使用系统;使用System.Collections.Generic;使用来;使用text;使用System.Threading.Tasks;使用System.Diagnostics;使用先;使用System.Data;

      ConsoleApplication1

      名称空间{类项目{静态void Main(string[] args){string sourceFile = @"C:testtempfile.csv";字符串行;Int count = 0;int commaccount = 0;int headercommaccount = 0;字符串templine;string destinationFile = @"C:testdestFile.csv";

      列表行= new List(); // Delete temporary destination file if it already exists if (File.Exists(destinationFile)) { File.Delete(destinationFile); } // Create temporary destination file File.Create(destinationFile).Dispose(); if (File.Exists(sourceFile)) { StreamReader file = null; try { file = new StreamReader(sourceFile); while ((line = file.ReadLine()) != null) { // If Header line, get the number of commas. This is the base by which all following rows will be compared. if (count == 0) { HeaderCommaCount = line.Split(',').Length - 1; lines.Add(line); //save to a string array count++; } else // This is any row following header row { commaCount = line.Split(',').Length - 1; if (commaCount == HeaderCommaCount) //Row following header contains the correct number of columns { lines.Add(line); //save to a string array count++; } else { templine = line; // If comma count is less than that of Header row, continue reading rows until it does and then write. while (commaCount != HeaderCommaCount) { line = file.ReadLine(); templine = templine + " " + line; commaCount = templine.Split(',').Length - 1; line = templine; if (commaCount == HeaderCommaCount) { lines.Add(line); //save to a string array } } } } } } finally { if (file != null) file.Close(); } } File.WriteAllLines(destinationFile, lines); //send contents of string array to destination file. //Console.ReadLine(); } } 之前

      }

    我将此快速编写为控制台应用程序,以便更容易转换为c#脚本任务。该文件测试成功,我应用了您的初始文件的例子。它将遍历源文本文件,并将分开的行连接在一起,然后保存到目标文件中。每次运行目标文件时,都会重新创建并填充目标文件。您可以首先在Visual Studio中作为控制台应用程序进行测试,并在代码中看到lines.Add(line)的上方或下方应用console.writeline(line)命令。

    在此之后,您所需要做的就是从临时目标文件导入到您的数据库。

    希望这对你有帮助。

    最新更新