微軟BI 之SSIS 系列 - ETL 轉換時關於 Code Page (1252 and 936) 轉換錯誤的原因和解決方法


開篇介紹

最近經常碰到在 ETL 練習中出現這種轉換失敗的問題,試了多種方式,同樣的代碼同樣的源結構和表結構但是一直不能成功執行,包報錯。一般有這么幾種錯誤:

Error at DST_LOAD_DATA_FROM_FILE [OLE_DST_EMPLOYEE[109]]: The column "FirstName" cannot be processed because more than one code page (1252 and 936) are specified for it.

或者就是

[OLE DB Destination [2]] Error: SSIS Error Code DTS_E_OLEDBERROR.  An OLE DB error has occurred. Error code: 0x80004005.

An OLE DB record is available.  Source: "Microsoft SQL Server Native Client 11.0"  Hresult: 0x80004005  Description:

"OLE DB provider 'STREAM' for linked server '(null)' returned invalid data for column '[!BulkInsert] .FirstName'.".

那么這些問題是如何造成的呢?

不一致的字符集

這些錯誤與兩方面因素有關,一方面是數據源,一方面是目標表。

在我們的測試案例文件中,源案例文件中包含有一些西歐字符,西歐拉丁字符集就是 1252。而我們有些測試環境下目標數據庫中的字符集是 GBK - 表示簡體中文,那么這種轉換要么就是轉換失敗,要么就是轉換成功但是顯示為亂碼。

下圖是我們的源文件中的西歐拉丁字符,這種字符是無法存儲在 GBK 字符集格式下的數據庫中的,強行存儲就是一個亂碼。

右鍵查看我們的目標表,如果它的 Collation 是 SQL_Latin1_General_CP1_CI_AS 的話這種文件數據加到對應的表中是沒有任何問題的。

但是如果是這樣的 Collation 就會出現錯誤。

錯誤還原

創建數據流 Data Flow Task 並設置文件數據源和目標表對象(Collation = Chinese_PRC_CI_AS),文件連接管理器中的 Locale 是英語,Code Page 是 1252。

已經可以看到報錯信息了:

The column "FirstName" cannot be processed because more than one code page (1252 and 936) are specified....

如果強制執行,就會看到這種信息:

Error at DST_OAD_DATA_FROM_FILE [OLE_DST_EMPLOYEE[109]]: The column "FirstName" cannot be processed because more than one code page (1252 and 936) are specified for it.

Error at DST_LOAD_DATA_FROM_FILE [OLE_DST_EMPLOYEE[109]]: The column "FirstName" cannot be processed because more than one code page (1252 and 936) are specified for it.

錯誤的原因在於數據流 DST_LOAD_DATA_FROM_FILE 中的數據流控件 OLE_DST_EMPOYEE 即 OLE DB Destination 目標控件中的列有多於一個以上的 Code Page 1252 和 936。 很顯然 1252 指的是自動識別到的文件數據源中的字符集是拉丁西歐字符 1252, 而 936 則表示我們目標表中的字符格式。目標控件不知道如何選擇哪一種字符集來處理,不統一就無法處理。

我們將文件鏈接管理器中的 Locale 改成簡體中文 Chinese Simplified, Code Page 自動變為 936 GBK 類型。

這時的包編輯通過。

但執行再次報錯。

錯誤原因:

[OLE DB Destination [2]] Error: SSIS Error Code DTS_E_OLEDBERROR.  An OLE DB error has occurred. Error code: 0x80004005.

An OLE DB record is available.  Source: "Microsoft SQL Server Native Client 11.0"  Hresult: 0x80004005  Description:

"OLE DB provider 'STREAM' for linked server '(null)' returned invalid data for column '[!BulkInsert] .FirstName'.".

注意到錯誤最后有一個 Bulk Insert 的插入方式,提示了我們在 OLE_DST_EMPLOYEE 控件中使用的是 Bulk Insert 的插入方式。Bulk Insert 又稱之為數據拷貝,速度和效率都很高,但是在 Bulk Insert 的過程中是不考慮字符轉換的,如果字符不能完成相應的轉換,一旦無法存儲就會發生報錯。

可以想一想,我們的源文件中的拉丁西歐字符是無法轉換成對應的 GBK 簡體中文的,所以在 OLE_DST_EMPLOYEE 中一定采用了 Bulk Insert 的方式,並且由於沒有字符轉換這一過程,GBK 的數據類型是無法保存這種西歐拉丁字符的。

為什么是 Bulk Insert 的方式,可以看看 OLE_DST_EMPLOYEE 就明白了,這里采用的是 Table or View - Fast Load 的模式。 Fast Load 只所以效率高,是因為它采用的就是 Bulk Insert 這種方式。

這也就是很多同學將 Table or view - Fast Load 改為 Table or view 就不會發生執行失敗的原因。因為在普通的 Table or view 的加載模式下,這種字符類型會強制的變為 GBK 可接受的數據格式。

執行成功了。

但是到數據庫中查查就會發現這個西歐字符實際上是沒有轉換成功的,變成了亂碼。而這個亂碼是不受我們控制的,因為目標數據庫,表的 Collation 就是 GBK 格式。

 

Code Page 的相關文章

什么是 Code Page  

更多 BI 文章請參看 BI 系列隨筆列表 (SSIS, SSRS, SSAS, MDX, SQL Server)  如果覺得這篇文章看了對您有幫助,請幫助推薦,以方便他人在 BIWORK 博客推薦欄中快速看到這些文章。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM