2012-03-06 49 views
2

大家好我在嘗試從文本文件導入數據時使用BULK INSERT命令時遇到了一個難題。用格式文件和批量插入導入SQL Server

我在網上發現了很多關於用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 
); 

對於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'); 

的錯誤是:

Bulk load data conversion error (type mismatch or invalid character for the specified codepage) for row 2, column 2 (begin_time).

我搜索了這個問題,嘗試將datetime更改爲smalldate,嘗試將長度更改爲23或24.它不起作用。所以我嘗試導入另一個表中沒有日期,我用數字列和字符列,但我面臨着與數字列了同樣的問題:

Bulk load data conversion error (type mismatch or invalid character for the specified codepage) for row 2, column 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 row(s) affected)

我也試着做例子http://msdn.microsoft.com/en-us/library/ms178129.aspx,但臉上帶着錯誤:

Cannot bulk load because the file "D:\myTest.txt" could not be read. Operating system error code (null).

而最後,我試圖用bcp這個程序和麪對錯誤。

任何人都可以幫助我解決我的問題,或者給我至少一個使用批量插入和格式文件的工作示例。

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

+0

您是否試圖跳過源數據中的任何列?儘管能夠在格式文件中命名列,但我認爲它不重要(我可能是錯的)。它依賴於列的序號位置。我使用XML格式文件和'openrowset'方法獲得了最好的運氣。 – gangreen 2012-03-06 08:31:14

回答

3

謝謝大家。但問題是MS SQL Server需要SQLCHAR類型,從文本文件導入時,數據庫中的列類型無關緊要。在我的問題中,解決方案是將格式文件中的所有列類型(如SQLNUMERIC,SQLDATETIME)替換爲SQLCHAR。

+0

在您使用的格式文件模板上讀了一點之後,它看起來像其他類型,如SQLNUMERIC,用於SQL Server本機格式的數據文件。原生格式= SQL Server內部二進制數據格式。由於您的數據不是原生格式,因此失敗(更多信息請訪問http://msdn.microsoft.com/zh-cn/library/aa173851%28v=sql.80%29.aspx)。無論如何,基於XML的格式文件,就像在我的例子中一樣,給你在使用數據類型上更多的靈活性。 – gangreen 2012-03-09 04:35:27

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