Sql-Server

是否可以使用 OPENROWSET 導入固定寬度的 UTF8 編碼文件?

  • December 10, 2021

我有一個包含以下內容並使用 UTF8 編碼保存的範例數據文件。

oab~opqr
öab~öpqr
öab~öpqr

該文件的格式為固定寬度,第 1 到第 3 列各分配 1 個字元,第 4 列保留 5 個字元。

我創建了一個 XML 格式文件,如下所示

<?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 xsi:type="CharFixed" ID="Col1" LENGTH="1"/>       
     <FIELD xsi:type="CharFixed" ID="Col2" LENGTH="1"/> 
     <FIELD xsi:type="CharFixed" ID="Col3" LENGTH="1"/> 
     <FIELD xsi:type="CharFixed" ID="Col4" LENGTH="5"/> 
     <FIELD xsi:type="CharTerm" ID="LINE_BREAK" TERMINATOR="\n"/> 
  </RECORD>  
  <ROW>  
     <COLUMN SOURCE="Col1" NAME="Col1" xsi:type="SQLNVARCHAR"/>  
     <COLUMN SOURCE="Col2" NAME="Col2" xsi:type="SQLNVARCHAR"/> 
     <COLUMN SOURCE="Col3" NAME="Col3" xsi:type="SQLNVARCHAR"/>  
     <COLUMN SOURCE="Col4" NAME="Col4" xsi:type="SQLNVARCHAR"/> 
  </ROW>  
</BCPFORMAT>

令人失望地執行以下 SQL…

SELECT *
FROM OPENROWSET
(
BULK 'mydata.txt',
FORMATFILE = 'myformat_file.xml',
CODEPAGE = '65001'
) AS X

產生以下結果

Col1 Col2 Col3 Col4
---- ---- ---- -----
o    a    b    ~opqr
�    �    a    b~öp
�    �    a    b~öp

我從中得出的結論LENGTH是計算字節而不是字元。

有什麼方法可以讓這個使用 UTF8 編碼的固定字元寬度正常工作嗎?

(目標環境是從 Blob 儲存讀取的 Azure SQL 數據庫)

COLLATION="LATIN1_GENERAL_100_CI_AS_SC_UTF8"注意:評論中建議添加FIELD元素可能會有所幫助,但結果保持不變。

我從中得出的結論LENGTH是計算字節而不是字元。

這是正確的,沒有辦法改為字元。

這種情況類似於char( n )、varchar( n )、nchar( n ) 和 nvarchar( n ) 中的**n,其中“n”表示字節數,而不是字元數。請參閱文件

一個常見的誤解是認為 CHAR(n) 和 VARCHAR(n) 中的 n 定義了字元數。但在 CHAR(n) 和 VARCHAR(n) 中,n 定義了以字節為單位的字元串長度 (0-8,000)。n 從不定義可以儲存的字元數。這類似於 NCHAR(n) 和 NVARCHAR(n) 的定義。產生這種誤解是因為在使用單字節編碼時,CHAR 和 VARCHAR 的儲存大小為 n 字節,字元數也是 n。但是,對於 UTF-8 等多字節編碼,更高的 Unicode 範圍 (128-1,114,111) 會導致一個字元使用兩個或更多字節。

這讓許多人感到困惑,尤其是在引入UTF-8 支持之後。以前可以使用 n(var)char 和補充字元,但我會說相對很少遇到。

如果 SQL Server將來在多個領域(包括 OPENROWSET)擴展其對字元而不是字節的支持,那就太好了。

同時,您的解決方法也是我可能會使用的解決方法。

引用自:https://dba.stackexchange.com/questions/303337