使用格式文件和批量插入导入SQL Server

时间:2012-03-06 08:13:35

标签: sql-server-2005 import bulkinsert file-format bcp

大家好,我在尝试从文本文件导入数据时遇到使用BULK INSERT命令的难题。

我在互联网上发现了很多关于使用BULK INSERTBCP计划进行导入的文章和示例,但它们对我没有帮助。

问题:
我从Oracle导出到包含列分隔符{#}和行分隔符<#>的文本文件,并将其导入SQL Server。

该表是(SQL Server):

CREATE TABLE my_DATA
(
ID_PK     NUMERIC(30)  NOT NULL ,
BEGIN_TIME    DATETIME  NULL ,
END_TIME      DATETIME  NULL
);

for Oracle:

CREATE TABLE my_DATA
(
ID_PK     NUMBER(30)  NOT NULL ,
BEGIN_TIME    TIMESTAMP  NULL ,
END_TIME      TIMESTAMP  NULL
);

带分隔符的文件是:

ID_PK{#}BEGIN_TIME{#}END_TIME<#>296167{#}01/01/2012 01:30:00.000{#}01/01/2012 02:00:00.000<#>296178{#}01/01/2012 02:00:00.000{#}01/01/2012 02:30:00.000<#>

格式文件是:

9.0                         
3                           
1   SQLNUMERIC  0   19  {#} 1   ID_PK   ""
2   SQLDATETIME 0   8   {#} 2   BEGIN_TIME  ""
3   SQLDATETIME 0   8   <#> 3   END_TIME    ""

所以当我使用命令时:

BULK INSERT my_DATA 
FROM 'D:\my_DATA.txt' 
WITH 
(CODEPAGE = '1251',
 FIELDTERMINATOR = '{#}', 
 FIRSTROW = 2, 
 ROWTERMINATOR = '<#>' );

它可以工作,但是当我尝试使用格式文件时,它不起作用:

BULK INSERT my_DATA 
FROM 'D:\my_DATA.txt' 
WITH (CODEPAGE = '1251',
      FORMATFILE ='D:\format_file.txt');

错误是:

  

批量加载数据转换错误(类型不匹配或无效字符   对于第2行,第2列(begin_time)的指定代码页。

我搜索了这个问题,尝试将datetime更改为smalldate,尝试将长度更改为23或24.它不起作用。所以我尝试导入另一个没有日期的表,我使用数字列和char列,但我遇到了与数字列相同的问题:

  

批量加载数据转换错误(类型不匹配或无效字符   对于第2行第1列(id_pk)。

的指定代码页

表:

CREATE TABLE unit_table
(
id_pk  NUMERIC(30)  NOT NULL ,
name             NVARCHAR(200)  NULL ,
name_full        NVARCHAR(200)  NULL ,
CONSTRAINT  PK_unit_table_2C1 PRIMARY KEY (bule_biz_unit_level_id_pk)
);

格式文件:

9.0
3
1       SQLNUMERIC    0       1      "{#}"      1     id_pk                              ""
2       SQLNCHAR      0       11     "{#}"      2     name                                              ""
3       SQLNCHAR      0       11     "{#}"      3     name_full                                         ""

数据文件只包含3行(批量插入命令相同):

ID_PK{#}NAME{#}NAME_FULL<#>1{#}factory{#}factory<#>2{#}station{#}station<#>

如果文件只包含2行,那就很有趣了:

ID_PK{#}NAME{#}NAME_FULL<#>1{#}factory{#}factory<#>

批量插入的结果是:

  

(0行(s)受影响)

我也尝试做示例http://msdn.microsoft.com/en-us/library/ms178129.aspx,但面对错误:

  

无法批量加载,因为无法读取文件“D:\ myTest.txt”。   操作系统错误代码(null)。

最后,我尝试在bcp程序中使用它并面对错误。

任何人都可以帮我解决我的问题,或者至少给我一个关于批量插入和格式文件的工作示例。

P.S。我使用MS SQL Server 2005更新到最新版本。操作系统是Windows 7 x64。

2 个答案:

答案 0 :(得分:3)

感谢所有人。但问题是,当您从文本文件导入时,MS SQL Server需要SQLCHAR类型,并且数据库中的列类型无关紧要。在我的问题中,解决方案是将任何列类型(如SQLNUMERIC,SQLDATETIME)替换为格式文件中的SQLCHAR。

答案 1 :(得分:1)

这不是你要求的,但我已经测试了它,应该让你到达你需要去的地方。据我所知,需要从托管SQL Server的服务器执行以下操作。您可以设置一个计划任务或更复杂的事情。

首先,您需要创建格式文件。我在示例中添加了不同的数据类型,以显示它们应该如何使用。

<?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="24"/>
  <FIELD ID="2" xsi:type="CharTerm" TERMINATOR="{#}" MAX_LENGTH="35" COLLATION="SQL_Latin1_General_CP1_CI_AS"/>
  <FIELD ID="3" xsi:type="CharTerm" TERMINATOR="{#}" MAX_LENGTH="12"/>
  <FIELD ID="4" xsi:type="CharTerm" TERMINATOR="{#}" MAX_LENGTH="41"/>
  <FIELD ID="5" xsi:type="CharTerm" TERMINATOR="<#>" MAX_LENGTH="30"/>
 </RECORD>
 <ROW>
  <COLUMN SOURCE="1" NAME="RpPrdEndDt" xsi:type="SQLDATETIME"/>
  <COLUMN SOURCE="2" NAME="ContrCustNum" xsi:type="SQLVARYCHAR"/>
  <COLUMN SOURCE="3" NAME="ClimateZone" xsi:type="SQLINT"/>
  <COLUMN SOURCE="4" NAME="BCMsrQty" xsi:type="SQLDECIMAL" PRECISION="16" SCALE="3"/>
  <COLUMN SOURCE="5" NAME="RMsrPricePerUnit" xsi:type="SQLMONEY"/>
 </ROW>
</BCPFORMAT>

其次,您需要为数据创建SQL INSERT语句:

INSERT INTO TableName
            (RpPrdEndDt,
             ContrCustNum,
             ClimateZone,
             BCMsrQty,
             RMsrPricePerUnit)
SELECT RpPrdEndDt,
       ContrCustNum,
       ClimateZone,
       BCMsrQty,
       RMsrPricePerUnit
FROM   OPENROWSET(BULK 'C:\ImportFileName.csv',
                  FORMATFILE='C:\FormatFile.xml' ) AS t1; 

第三,如果你想从命令行运行它,就像BCP一样,你可以使用它:

sqlcmd -S ServerName\InstanceName -i C:\SavedSQLFile.sql