erlang:odbc-无法从mssql的unicode中获取正确的查询结果

时间:2019-06-26 20:08:00

标签: sql-server unicode odbc elixir freetds

我正在尝试的是:  -只需从elixir中使用erlang-odbc进行选择,然后将所有结果转储到控制台即可。

环境: 我的身边

  • Red Hat Enterprise Linux Server 7.6(Maipo)
  • unixODBC-devel(yum)
  • Elixir 1.8.2(与Erlang / OTP 20编译)
  • Erlang / OTP 21
  • erlang-odbc R16B(百胜)
  • (两个)mssql驱动程序
  • (或)FreeTds驱动程序1.1.6(从--with-unixodbc编译)

目标

  • mssql服务器2016


    CREATE TABLE db_name.dbo.rating (
        [Year] int NULL,
        Code varchar(256) COLLATE Cyrillic_General_CI_AS NULL,
        Name nvarchar(4000) COLLATE Cyrillic_General_CI_AS NULL,
        GroupeCode varchar(256) COLLATE Cyrillic_General_CI_AS NULL,
        GroupeName nvarchar(4000) COLLATE Cyrillic_General_CI_AS NULL,
        Cost numeric(38,5) NOT NULL,
        PrchasesCount int NULL
        ) GO

nvarchar :     character_set_name:UNICODE     排序规则名称:Cyrillic_General_CI_AS

varchar :     character_set_name: cp1251     排序规则名称:Cyrillic_General_CI_AS

elixir代码如下:

conn_str = 
    "SERVER=XX.XX.XX.XX,1433;" <>
     #tried this too! "DRIVER={ODBC Driver 17 for SQL Server};" <>
    "DRIVER=FreeTDS;" <>
    "DATABASE=db_name;UID=bot;PWD=XXXXXX;" 
|> to_charlist

 statement = "select top(3) Name from Rating order by Cost desc" |> to_charlist

 {:ok, pid}=:odbc.connect(conn_str,[])

 {:selected, col_names, rows} = :odbc.sql_query(pid, statement)

在所有尝试之后,我的结果都是这样的

{:selected, ['Name'],
 [
   {<<32, 4, 48, 4, 49, 4, 62, 4, 66, 4, 75, 4, 32, 0, 65, 4, 66, 4, 64, 4, 62,
      4, 56, 4, 66, 4, 53, 4, 59, 4, 76, 4, 61, 4, 75, 4, 53, 4, 32, 0, 63, 4,
      62, 4, 32, ...>>},
   {<<16, 4, 64, 4, 53, 4, 61, 4, 52, 4, 48, 4, 32, 0, 63, 4, 48, 4, 65, 4, 65,
      4, 48, 4, 54, 4, 56, 4, 64, 4, 65, 4, 58, 4, 62, 4, 51, 4, 62, 4, 32, 0,
      66, 4, ...>>},
   {<<35, 4, 65, 4, 59, 4, 67, 4, 51, 4, 56, 4, 32, 0, 63, 4, 62, 4, 32, 0, 64,
      4, 53, 4, 58, 4, 67, 4, 59, 4, 76, 4, 66, 4, 56, 4, 50, 4, 48, 4, 70, 4,
      56, ...>>}
 ]}

代替正确的西里尔字母

它不是随机数!结果总是一样。

MS驱动程序提供与FreeTDS相同的结果

我还尝试了什么

  • 更改conn选项binary_strings::on / off
  • 在freetds.conf中(在全局部分中)设置选项客户端字符集= UTF-8
  • 挠头
  • 使用:unicode函数读取<<数据>>
  • 在接收到的号码上使用is_binary()返回true

问题

  • 我会收到什么类型的数据?
  • 为什么数据解码不正确?
  • 什么应用负责?
  • 我该如何解决? freetds的某些部分在此处登录(关于iconv)
iconv.c:326:tds_iconv_open(0x1e02330, UTF-8)
iconv.c:186:local name for ISO-8859-1 is ISO-8859-1
iconv.c:186:local name for UTF-8 is UTF-8
iconv.c:186:local name for UCS-2LE is UCS-2LE
iconv.c:186:local name for UCS-2BE is UCS-2BE
iconv.c:348:setting up conversions for client charset "UTF-8"
iconv.c:350:preparing iconv for "UTF-8" <-> "UCS-2LE" conversion
iconv.c:389:tds_iconv_open: done
iconv.c:785:setting server single-byte charset to "CP1251"

1 个答案:

答案 0 :(得分:0)

如果您使用的是SQL Server 2019,将要使用以_UTF8而不是_AS结尾的排序规则。这里有完整的文章,其中包含有关归类类型的详细信息:

https://docs.microsoft.com/en-us/sql/relational-databases/collations/collation-and-unicode-support?view=sql-server-2017#utf-8-support

MSSQL 2019之前的版本

我知道这适用于Python 3。