我正在尝试BULK插入CSV

时间:2012-10-25 12:01:12

标签: sql-server csv bulkinsert

我从客户端获取CSV,我需要将该文件导入数据库。我经历了无数的迭代,无限的解决方案测试的一部分。当我需要完整的解决方案时,我的问题就来了。

CSV有14个字段,tempdb数据库有15个字段(最后一个是标识列)。数据在没有标识的情况下到达,我根据数据库设计需要一行唯一编号。

我模糊了显示的测试数据,但它模仿了数据。

T2012-DAT;09-01-2012;09-01-2012;1;910,91;12;TST;4,55;200,2;6;;;;7,5
T2012-DAT;10-01-2012;10-01-2012;1;910,91;12;TST;4,55;200,2;6;;;;7,5
T2012-DAT;11-01-2012;11-01-2012;1;910,91;12;TST;4,55;200,2;6;;;;7,5
T2012-DAT;12-01-2012;12-01-2012;1;910,91;12;TST;4,55;200,2;6;;;;7,5
T2012-DAT;13-01-2012;13-01-2012;1;910,91;12;TST;4,55;200,2;6;;;;7
T2012-DAT;16-01-2012;16-01-2012;1;910,91;12;TST;4,55;200,2;6;;;;7,5

我在tempdb中创建的临时表。您会注意到它有15个字段,最后一个是所需的标识。

CREATE TABLE BudgetImport(
    sBudgetName varchar(20) COLLATE Danish_Norwegian_CI_AS  
    , dStartDate varchar(12) COLLATE Danish_Norwegian_CI_AS  
    , dEndDate varchar(12) COLLATE Danish_Norwegian_CI_AS   
    , prCode int   
    , decTotal varchar(20) COLLATE Danish_Norwegian_CI_AS
    , sRefTimeTypeID varchar(10) COLLATE Danish_Norwegian_CI_AS  
    , sRefEmployeeID varchar(10) COLLATE Danish_Norwegian_CI_AS  
    , decHours varchar(20) COLLATE Danish_Norwegian_CI_AS  
    , decRate varchar(20) COLLATE Danish_Norwegian_CI_AS
    , sDepartmentID varchar(10) COLLATE Danish_Norwegian_CI_AS NULL  
    , sCentre varchar(10) COLLATE Danish_Norwegian_CI_AS NULL  
    , sPurpose varchar(10) COLLATE Danish_Norwegian_CI_AS NULL  
    , sProjectID varchar(10) COLLATE Danish_Norwegian_CI_AS NULL  
    , decNormHours varchar(20) COLLATE Danish_Norwegian_CI_AS  
    --, iRowNumber int identity(500000,1)  
)

GO

 -- import data by csv
 BULK INSERT BudgetImport
 FROM 'D:\budgetposter.csv'
 WITH
 (
    fieldterminator = ';'
    , rowterminator = '\r\n'
    , codepage = '1252'
 )

当我包含身份时,我收到此错误:

Msg 4866, Level 16, State 1, Line 3
The bulk load failed. The column is too long in the data file for row 1, column 15. Verify that the field terminator and row terminator are specified correctly.

如果我将其排除,则错误更改为:

Msg 4866, Level 16, State 1, Line 3
The bulk load failed. The column is too long in the data file for row 1, column 14. Verify that the field terminator and row terminator are specified correctly.

如果我更改了rowterminator = '\n' ,则会通过,但我错过了身份。

如果我然后包含身份,则错误变为:

Msg 4864, Level 16, State 1, Line 3
Bulk load data conversion error (type mismatch or invalid character for the specified codepage) for row 1, column 15 (iRowNumber).

当我在测试时,我将INSERT INTO dbo."the-real-datatable"排除在外,只是单独执行SELECT FROM BudgetImport。因此,我避免在real-datatable中插入另外16000行。

如果你注意并知道匈牙利符号,你会注意到我正在使用varchars,即使datatime或decimal可能是正确的形式。经过约4-6小时的测试和无休止的头痛和头发撕裂,我正在这样做。 Varchar是KISS解决方案,我稍后会CONVERT()

我的整个问题围绕行中的最后一个字段解决。 - 我试过添加1和2;在decNormHours之后,我尝试添加空值(;;或; 1;或; n;)。 - 我尝试过使用formatfile.xml - 再没有蛋糕。没有格式文件比使用格式文件更成功。 - 我尝试过更改为英国数字表示法。 =使用DK表示法更成功。 - 我已经尝试过每一个我能想到的技巧都无济于事。

是的,CSV中没有标识字段,没关系。您只需使用我在表创建中描述的默认自动identity(500000,1)。哦500000是我现在达到的近似行ID,它会随着时间的推移而增加。

拜托,接下来我需要尝试什么才能做到这一点?

编辑:
使用格式文件

$lt;? xml version="1.0 " ? $gt;
$lt;BCPFORMAT xmlns="http://schemas.microsoft.com/sqlserver/2004/bulkload/format" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"$gt;
 $lt;RECORD$gt;
  FIELD ID="1" xsi:type="NCharTerm" TERMINATOR=";" COLLATION="SQL_Latin1_General_CP1_CI_AS"/
  FIELD ID="2" xsi:type="CharFixed" LENGTH="9" COLLATION="SQL_Latin1_General_CP1_CI_AS"/
  FIELD ID="3" xsi:type="CharFixed" LENGTH="9" COLLATION="SQL_Latin1_General_CP1_CI_AS"/
  FIELD ID="4" xsi:type="NCharTerm" TERMINATOR=";"/
  FIELD ID="5" xsi:type="NCharTerm" TERMINATOR=";"/
  FIELD ID="6" xsi:type="NCharTerm" TERMINATOR=";" MAX_LENGTH="20" COLLATION="SQL_Latin1_General_CP1_CI_AS"/
  FIELD ID="7" xsi:type="NCharTerm" TERMINATOR=";" MAX_LENGTH="20" COLLATION="SQL_Latin1_General_CP1_CI_AS"/
  FIELD ID="8" xsi:type="NCharTerm" TERMINATOR=";"/
  FIELD ID="9" xsi:type="NCharTerm" TERMINATOR=";"/
  FIELD ID="10" xsi:type="NCharTerm" TERMINATOR=";" MAX_LENGTH="20" COLLATION="SQL_Latin1_General_CP1_CI_AS"/
  FIELD ID="11" xsi:type="NCharTerm" TERMINATOR=";" MAX_LENGTH="50" COLLATION="SQL_Latin1_General_CP1_CI_AS"/
  FIELD ID="12" xsi:type="NCharTerm" TERMINATOR=";" MAX_LENGTH="50" COLLATION="SQL_Latin1_General_CP1_CI_AS"/
  FIELD ID="13" xsi:type="NCharTerm" TERMINATOR=";" MAX_LENGTH="20" COLLATION="SQL_Latin1_General_CP1_CI_AS"/
  FIELD ID="14" xsi:type="NCharTerm" TERMINATOR=";"/
 /RECORD
 ROW
  COLUMN SOURCE="1" NAME="sBudgetName" xsi:type="SQLNVARCHAR" LENGTH="20" /
  COLUMN SOURCE="2" NAME="dStartDate" xsi:type="SQLDATETIME"/
  COLUMN SOURCE="3" NAME="dEndDate" xsi:type="SQLDATETIME"/
  COLUMN SOURCE="4" NAME="prCode" xsi:type="SQLSMALLINT"/
  COLUMN SOURCE="5" NAME="decTotal" xsi:type="SQLDECIMAL"/
  COLUMN SOURCE="6" NAME="sRefTimeTypeID" xsi:type="SQLNVARCHAR" LENGTH="10"/
  COLUMN SOURCE="7" NAME="sRefEmployeeID" xsi:type="SQLNVARCHAR" LENGTH="10"/
  COLUMN SOURCE="8" NAME="decHours" xsi:type="SQLDECIMAL"/
  COLUMN SOURCE="9" NAME="decRate" xsi:type="SQLDECIMAL"/
  COLUMN SOURCE="10" NAME="sDepartmentID" xsi:type="SQLNVARCHAR" LENGTH="10"/
  COLUMN SOURCE="11" NAME="Centre" xsi:type="SQLNVARCHAR" LENGTH="10"/
  COLUMN SOURCE="12" NAME="Purpose" xsi:type="SQLNVARCHAR" LENGTH="10"/
  COLUMN SOURCE="13" NAME="sRefProjectID" xsi:type="SQLNVARCHAR" LENGTH="10"/
  COLUMN SOURCE="14" NAME="decNormHours" xsi:type="SQLDECIMAL"/
/ROW

让我重新开始让第一个领域正确运作。因此,在争取最终细节的斗争中,我最终会争取让它在第一时间起作用/正在做任何事情。 错误:

Msg 4863, Level 16, State 1, Line 3
Bulk load data conversion error (truncation) for row 1, column 1 (sBudgetName).
注意:嗯,似乎SO不喜欢xml。多奇怪。

1 个答案:

答案 0 :(得分:0)

这是一种解决方法而非解决方案,但由于您遇到列数问题,为什么不在之后添加索引列?

你可以这样做:

  • 将CSV导入具有相同列数的临时表

然后,

ALTER TABLE BudgetImport
    ADD Id  INTEGER
GO

WITH Cte
AS
(
    SELECT *
    , ROW_NUMBER() OVER(ORDER BY [**column of your choice**] DESC) AS RowNumber
    FROM BudgetImport
)
UPDATE Cte
SET Id = RowNumber
GO

ALTER TABLE BudgetImport
ALTER COLUMN Id INTEGER NOT NULL 
GO

ALTER TABLE BudgetImport
ADD PRIMARY KEY (Id)
GO