再踩 SQL 資料庫地雷一枚。

配合停用 TLS 1.0,把一些老舊程式用的 ODBC 版本升級到 ODBC 17 (參考:ODBC 與 OLEDB 之 SQL Server TLS 1.2 支援問題),遇到詭異現象:升級後有個 SELECT ColKey, ColContent FROM ... 查詢傳回的 ColKey 內容正常, ColContent 則是空字串。換版前並無此問題,同一程式在另一台測試環境也正常。

經過比對測試,發現關鍵在於 ColContent 欄位型別是 NVARCHAR(MAX),用 SELECT CONVERT(NVARCHAR(MAX), 'TEST') 也能重現問題。 至於可正常執行的測試環境,與問題環境差在 DSN 用的驅動程式是 SQL Server 10.0 Client,而非 ODBC Driver 17 for SQL Server。 由此推論:某些版本 ODBC SQL 驅動程式不支援 NVARCHAR(MAX)。在測試機器找到四種 SQL 驅動程式:ODBC Driver 13 for SQL Server、ODBC Driver 17 for SQL Server、SQL Server 10.0、SQL Server Native Client 11.0,

為四種驅動程式各自建立 DSN:

使用以下程式驗證,若支援 NVARCHAR(MAX) 應該出現 123,ABC,否則只會看到 123,:

sqlCmd = "SELECT CONVERT(NVARCHAR(4000),N'123'),CONVERT(NVARCHAR(MAX), N'ABC')"

cn.open "DSN=ODBC17"
rs.open sqlCmd, cn, 0, 1, 1
Response.Write "<li> ODBC 17 Test="
Response.Write rs(0) & ","
Response.Write rs(1)
rs.Close
cn.Close

cn.open "DSN=ODBC13"
rs.open sqlCmd, cn, 0, 1, 1
Response.Write "<li> ODBC 13 Test="
Response.Write rs(0) & ","
Response.Write rs(1)
rs.Close
cn.Close

cn.Open "DSN=SQL11"
rs.Open sqlCmd, cn, 0, 1, 1
Response.Write "<li> SQL Naitve Client 11 Test="
Response.Write rs(0) & ","
Response.Write rs(1)
rs.close
cn.close

cn.Open "DSN=SQL10"
rs.Open sqlCmd, cn, 0, 1, 1
Response.Write "<li> SQL 10 Test="
Response.Write rs(0) & ","
Response.Write rs(1)
rs.close
cn.close

測試結果令人意外,除了較古老的 SQL Server Client 10.0,其餘全軍覆沒:

爬文查到幾篇相關文獻:

歸納結論:ODBC Driver 11 for SQL Server、ODBC Driver 13 for SQL Server、ODBC Driver 17 for SQL Server、SQL Native Client 都有查詢 VARCHAR(MAX) 傳回空白或亂碼的前科,一般建議換成 Microsoft OLE DB Driver for SQL Serve,而我測試 SQL Server 10.0 也沒問題。若無法換驅動程式,將 NVARCHAR(MAX) 轉型成 NVARCHAR(4000) 或 NTEXT 亦是 Workaround。

Case of selecting NVARCHAR(MAX) returns null with ODBC driver for SQL server.


Comments

Be the first to post a comment

Post a comment