简体   繁体   English

ODBC 中的 Haskell Unicode 列名

[英]Haskell Unicode column name in ODBC

I am trying to query some data from a MSSQL database through HDBC and ODBC .我正在尝试通过HDBCODBC从 MSSQL 数据库中查询一些数据。 I have however run into a problem when trying to query data from a table with unicode in the column names.但是,当我尝试从列名中包含 unicode 的表中查询数据时遇到了问题。

Consider the following MWE:考虑以下 MWE:

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

When executing the above and passing it a connection object to the database i get the following error message:执行上述操作并将连接对象传递给数据库时,我收到以下错误消息:

*** 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.\"]"}

The relevant part most likely being that H\\\\195\\\\184jde is not a valid column name.相关部分很可能是H\\\\195\\\\184jde不是有效的列名。

My research has mostly led to results about unicode in the parameters to the query.我的研究主要是在查询的参数中得出了关于 unicode 的结果。 I have tried to use bytestrings instead of normal strings, but since the argument for QuickQuery' is a string that did not help.我曾尝试使用字节串代替普通字符串,但由于QuickQuery'的参数是一个没有帮助的字符串。

I don't have an MS SQL instance to test this, but the code in HDBC-odbc encodes the query using UTF-8.我没有 MS SQL 实例来测试这个,但是HDBC-odbc代码使用 UTF-8 对查询进行编码。 Meanwhile, this documentation suggests that for modern ODBC drivers, the character set used for queries depends on the process locale at the time the driver is initialized.同时, 该文档表明,对于现代 ODBC 驱动程序,用于查询的字符集取决于驱动程序初始化时的进程区域设置。 If it's "C" , which is the usual process default, then the driver will use the UTF-8 character set.如果它是"C" ,这是通常的进程默认值,那么驱动程序将使用 UTF-8 字符集。 However, if the process executes:但是,如果进程执行:

setlocale(LC_ALL,"")

before initializing the driver, and the current Windows locale is, say, English using the Latin-1 1252 code page, then the ODBC driver will expect Latin-1 encoded queries.在初始化驱动程序之前,并且当前的 Windows 区域设置是使用 Latin-1 1252 代码页的英语,那么 ODBC 驱动程序将需要 Latin-1 编码的查询。 Unfortunately for you, the GHC runtime does run setlocale(LC_ALL,"") , so that's probably what's going wrong.不幸的是,GHC 运行时确实运行setlocale(LC_ALL,"") ,所以这可能是哪里出了问题。

If you reset the locale to "C" at the start of "main" , that may fix the issue:如果您在"main"开头将语言环境重置为"C" ,则可能会解决问题:

{-# 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"

I'm not sure if this will cause other problems (eg, with terminal input/output).我不确定这是否会导致其他问题(例如,终端输入/输出)。 If it does, you may be able to set the locale to "C" before initializing the driver and then reset it to "" right after.如果是这样,您可以在初始化驱动程序之前将语言环境设置为"C" ,然后立即将其重置为""

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM