批量插入.csv没有最后一行

时间:2018-03-26 23:17:52

标签: sql-server database

我有一个包含多行数据的.csv文件(请参阅图片)

data in .csv file

此数据由第三方提供,我无法更改格式。

我是BULK使用ms SQL服务器管理将这些数据插入SQL服务器表。

当我使用以下内容进行BULK插入时:

    BULK INSERT #tempDERIVEDDATA
    FROM 'C:\MyDownloads\Data.csv'
    WITH
    (FIRSTROW = 1,
    FIELDTERMINATOR = ',',
    ROWTERMINATOR = '0x0a',
    ERRORFILE = 'C:\MyDownloads\logfile.log')
    GO

我似乎得到以下错误:

  

消息4832,级别16,状态1,行236批量加载:意外结束   在数据文件中遇到文件。 Msg 7399,Level 16,State   1,第236行OLE DB提供程序“BULK”用于链接服务器“(null)”   报告错误。提供商没有提供任何有关的信息   错误。消息7330,级别16,状态2,行236无法从中获取行   OLE DB提供程序“BULK”用于链接服务器“(null)”。

当最后一行是页脚行并指出文件中的行数被删除时,批量插入工作。所以我甚至不能删除那一行,因为他们正在努力做到这一点。

那么我想如果使用OPENROWSET函数并计算行数并将(#rows - 1)插入表中会怎么样?

所以我尝试了下面的方法来计算行数:

   DECLARE @lastrow INT
   SET @lastrow = (SELECT COUNT(*) FROM OPENROWSET(BULK 'C:\MyDownloads\DATA1.csv', 
   FORMATFILE = 'C:\MyDownloads\format.fmt',
   MAXERRORS=10) AS  ) - 1
   SELECT @lastrow

选择的最后一行应该检索(#rows - 1)应该检索行数,但是我得到一个错误。

  

Msg 4832,Level 16,State 1,Line 230批量加载:意外结束   在数据文件中遇到了文件。 Msg 7399,Level 16,State 1,   第230行OLE DB提供程序“BULK”用于链接服务器“(null)”   报告错误。提供商没有提供任何有关的信息   错误。消息7330,级别16,状态2,行230无法从中获取行   OLE DB提供程序“BULK”用于链接服务器“(null)”。

格式文件如下: FORMAT.FMT

之后我决定使用格式文件,而不是SINGLE_CLOB。这次没有错误,但文件在检索'341'时会检索'0'行。

如果有人可以提供协助,我将不胜感激。

3 个答案:

答案 0 :(得分:0)

考虑使用openrowset。

    create procedure [dbo].LoadData
    (
            @file nvarchar(200)=null
    )
    as
    begin
            declare @sql varchar(max)
            set @sql='INSERT INTO DBO.Table
            (
                    column1, column2
            )
            select column1
                                    ,column2
            from openrowset(bulk N''' + @file +''',
             formatfile = N''d:\xml\Table.xml'') as t1
             where not column1 like (''Total'')'

             print @sql
             exec (@sql)
    end


    --- Table.xml

    <?xml version="1.0"?>
    <BCPFORMAT xmlns="http://schemas.microsoft.com/sqlserver/2004/bulkload/format" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
     <RECORD>
      <FIELD ID="1" xsi:type="CharTerm" TERMINATOR="," MAX_LENGTH="100" COLLATION="SQL_Latin1_General_CP1_CI_AS"/>
      <FIELD ID="2" xsi:type="CharTerm" TERMINATOR="," MAX_LENGTH="50" COLLATION="SQL_Latin1_General_CP1_CI_AS"/>
     </RECORD>
     <ROW>
      <COLUMN SOURCE="1" NAME="column1" xsi:type="SQLNVARCHAR"/>
      <COLUMN SOURCE="2" NAME="column2" xsi:type="SQLNVARCHAR"/>
     </ROW>
    </BCPFORMAT>

答案 1 :(得分:0)

Hummm,我在2015年遇到了完全相同的问题。你是否偶然在CapIQ工作?无论如何,我最终创建了一个C#可执行文件并运行它来清理文件,然后运行Bulk Insert脚本来加载数据。我实际上保存了那个解决方案,因为我觉得有一天我会再次需要它。这是解决方案。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Diagnostics;


namespace ConsoleApplication3
{
    class Program
    {
        static void Main(string[] args)
        {

            string sourceDirectory = @"C:\ManagedCode\Downloads\";
            try
            {
                var txtFiles = Directory.EnumerateFiles(sourceDirectory);

                foreach (string currentFile in txtFiles)
                {
                    //foreach (var currentFile in files)
                    {
                        var lines = File.ReadAllLines(currentFile);

                        //Just an example of changing the filename based upon the current name
                        var targetFile = Path.ChangeExtension(currentFile, "prod.txt");
                        File.WriteAllLines(targetFile, lines.Skip(1).Take(lines.Count() - 2));
                        //};

                    }

                }
            }

            catch (Exception ex)
            {

            }

        }
    }
}

您可以使用Windows任务管理器在您选择的任何计划上运行此可执行文件(以及任何可执行文件)。

答案 2 :(得分:0)

使用一个宽列创建一个临时表,并将整个行插入整个文件的该列中,然后使用select + insert从临时表中进行选择,并在选择时通过分隔符分隔字段,并排除最后一行。最后,将临时表放入准备中以进行下一次导入。