我想在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
有两种方法可以解决格式问题。
如果可能的话,最简单的方法是跟踪创建文件的人,并让他们正确地完成。例如,假设他们使用的是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)命令。
在此之后,您所需要做的就是从临时目标文件导入到您的数据库。
希望这对你有帮助。