pymssql在Azure / Windows上返回与Mac上不同的字符集

时间:2016-10-23 20:20:45

标签: python azure character-encoding pymssql

我在Azure上托管了一个sql server数据库。我在数据库中放了一个带有智能引号的字符串('“test”')。我可以连接到它并运行一个简单的查询:

import pymssql
import json

conn = pymssql.connect(
    server='coconut.database.windows.net',
    user='kingfish@coconut',
    password='********',
    database='coconut',
    charset='UTF-8',
)

sql = """
SELECT * FROM messages WHERE id = '548a72cc-f584-7e21-2725-fe4dd594982f'
"""
cursor = conn.cursor()
cursor.execute(sql)
row = cursor.fetchone()
json.dumps(row[3])

当我在Mac上运行此查询(macOS 10.11.6,Python 3.4.4,pymssql 2.1.3)时,我找回了字符串:

"\u201ctest\u201d"

这被正确解释为智能引号并正确显示。

当我在Azure Web部署(Python 3.4,Azure App服务)上运行此查询时,我得到了相同字符串的不同(和不正确)编码:

"\u0093test\u0094"

我在pymssql连接上将charset指定为'UTF-8'。为什么Windows / Azure环境会返回不同的字符集?

(注意:我已将预先构建的二进制文件pymssql-2.1.3-cp34-none-win32.whl放在我的项目仓库的驾驶室中。这与pymssql预构建的二进制文件pymssql-相同在PyPI上只有2.1.3-cp34-cp34m-win32.whl我必须将'cp34m'重命名为'none'以说服pip安装它。)

2 个答案:

答案 0 :(得分:2)

根据您的描述,我认为该问题似乎是由Azure上SQL数据库的默认字符集编码引起的。为了验证我的想法,我在Python 3中做了一些测试。

Azure上SQL数据库的默认字符集编码为Windows-1252 (CP-1252)

  

SQL Server Collation Support
  Microsoft Azure SQL数据库使用的默认数据库归类是SQL_LATIN1_GENERAL_CP1_CI_AS,其中LATIN1_GENERAL是英语(美国), CP1是代码页1252 ,CI是不区分大小写的,AS是重音敏感的。无法更改V12数据库的排序规则。有关如何设置排序规则的详细信息,请参阅COLLATE(Transact-SQL)。

>>> u"\u201c".encode('cp1252')
b'\x93'
>>> u"\u201d".encode('cp1252')
b'\x94'

如上所示代码,\u0093& \u0094可以通过编码\u201c& \u201d

>>> u"\u0093".encode('utf-8')
b'\xc2\x93'
>>> u"\u0093".encode('utf-8').decode('cp1252')[1]
'“'     # It's `\u201c`
>>> u"\u201c" == u"\u0093".encode('utf-8').decode('cp1252')[1]
True

因此,当您创建SQL数据库时,我认为当前用于数据存储的SQL数据库的charset编码为Latin-1,而不是UTF-8,如下图所示,默认属性{{1} Azure门户上的Collation。请尝试使用其他归类支持SQL_Latin1_General_CP1_CI_AS而不是默认支持。

enter image description here

答案 1 :(得分:1)

我最终将列类型从VARCHAR重新编辑为NVARCHAR。这解决了我的问题,无论平台如何,都能正确解释字符。