大家好,我在尝试从文本文件导入数据时遇到使用BULK INSERT
命令的难题。
我在互联网上发现了很多关于使用BULK INSERT
或BCP
计划进行导入的文章和示例,但它们对我没有帮助。
问题:
我从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。
答案 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