3

我正在尝试通过HDBCODBC从 MSSQL 数据库中查询一些数据。但是,当尝试从列名中包含 unicode 的表中查询数据时,我遇到了问题。

考虑以下 MWE:

mwe :: IConnection conn => conn -> IO [[SqlValue]]
mwe conn =
  do r <- quickQuery' conn
          "SELECT [Højde] FROM [Table]"
          []
     return r

执行上述操作并将连接对象传递给数据库时,我收到以下错误消息:

*** Exception: SqlError {seState = "[\"42S22\",\"42000\"]", seNativeError = -1, seErrorMsg = "execute execute: [\"207: [Microsoft][ODBC Driver 17 for SQL Server][SQL Server]Invalid column name 'H\\195\\184jde'.\",\"8180: [Microsoft][ODBC Driver 17 for SQL Server][SQL Server]Statement(s) could not be prepared.\"]"}

相关部分很可能H\\195\\184jde不是有效的列名。

我的研究主要导致了查询参数中有关 unicode 的结果。我尝试使用字节字符串而不是普通字符串,但是因为 for 的参数QuickQuery'是一个没有帮助的字符串。

4

1 回答 1

0

我没有一个 MS SQL 实例来测试它,但代码中的代码HDBC-odbc使用 UTF-8 对查询进行编码。同时,该文档建议对于现代 ODBC 驱动程序,用于查询的字符集取决于驱动程序初始化时的进程区域设置。如果是"C",这是通常的进程默认值,那么驱动程序将使用 UTF-8 字符集。但是,如果进程执行:

setlocale(LC_ALL,"")

在初始化驱动程序之前,如果当前的 Windows 区域设置是使用 Latin-1 1252 代码页的英语,那么 ODBC 驱动程序将需要 Latin-1 编码的查询。对您来说不幸的是,GHC 运行时确实运行setlocale(LC_ALL,""),所以这可能是问题所在。

"C"如果您在 开始时将语言环境重置为"main",则可能会解决问题:

{-# LANGUAGE ForeignFunctionInterface #-}

import Control.Monad
import Foreign.C
import Foreign.Ptr

foreign import ccall "locale.h setlocale" c_setlocale :: CInt -> CString -> IO CString

setCLocale :: IO ()
setCLocale = do
  rc <- withCString "C" $ c_setlocale 0
  when (rc == nullPtr) $ error "setCLocale failed"

main = do
  setCLocale
  print "whatever"

我不确定这是否会导致其他问题(例如,终端输入/输出)。如果是这样,您可以"C"在初始化驱动程序之前将语言环境设置为,然后在之后将其重置为""

于 2020-03-11T16:54:49.323 回答