【问题标题】:Import into SQL Server with format file and bulk insert使用格式文件和批量插入导入 SQL Server
【发布时间】:2012-03-06 08:13:35
【问题描述】:

大家好,当我尝试从文本文件导入数据时,我在使用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
);

对于甲骨文:

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 列(开始时间)。

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

批量加载数据转换错误(类型不匹配或无效字符 对于指定的代码页)对于第 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 行受影响)

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

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

最后,我尝试将它与bcp 程序一起使用,但也遇到了错误。

谁能帮我解决我的问题,或者至少给我一个关于批量插入和格式化文件的工作示例。

附:我使用更新到最新版本的 MS SQL Server 2005。操作系统是 Windows 7 x64。

【问题讨论】:

  • 您是否要跳过源数据中的任何列?尽管能够在格式文件中命名列,但我认为这并不重要(我可能是错的)。它依赖于列的序数位置。我在使用 XML 格式文件和 openrowset 方法时获得了最好的运气。

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


【解决方案1】:

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

【讨论】:

  • 在阅读了一些您使用的格式文件模板之后,看起来其他类型(如 SQLNUMERIC)用于 SQL Server Native 格式的数据文件。本机格式 = SQL Server 内部二进制数据格式。由于您的数据不是本机格式,因此它失败了(更多信息在这里 msdn.microsoft.com/en-us/library/aa173851%28v=sql.80%29.aspx )。无论如何,基于 XML 的格式文件,就像在我的示例中一样,让您在使用数据类型时更加灵活。
【解决方案2】:

这并不是您所要求的,但我已经对其进行了测试,应该可以将您带到您需要去的地方。据我所知,需要从托管 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

【讨论】:

    猜你喜欢
    • 2013-01-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-08-17
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多