在Python中检索到的SQL Server VARCHAR列的编码问题


10

最近,我们遇到了与字段相关的编码问题,该字段在SQL Server中存储为varchar(120)。在SSMS中,varchar显示为:

“谁杀了乔本?”

但是,将其引入python后,显示为:

在此处输入图片说明

我已经从Python方面对此进行了研究,并且没有任何奇怪的事情发生。我的理论是,SQL Server中的varchar接受的是UTF-8字符,这些字符在python中的显示方式不同于SSMS。我对SQL Server中的编码不是很熟悉。有人可以让我知道以下内容:

  • SSMS中有没有办法查看varchar的编码?例如,看到\ x82而不是显示当前来自SSMS的逗号?
  • 我们正在使用SQL Server2008。是否可以在不使用导入/导出工具或转储到平面文件的情况下,将任何UTF-8字符的编码更改为ASCII字符?即可以通过查询进行此转换吗?
  • 有什么方法可以通过查询以编程方式识别有问题的记录(问题定义为ASCII不支持的UTF-8字符)?

先感谢您!

使用,sp_help N'table_name';我发现此VARCHAR列的归类为SQL_Latin1_General_CP1_CI_AS


VARCHAR列使用什么排序规则?
所罗门·鲁兹基

@SolomonRutzky您如何检查排序规则。我不确定这意味着什么
Eric

我认为最快的方法是:sp_help N'table_name';。查看基于“名称”的列,然后查看“ collat​​ion_name”列。
所罗门·鲁兹基

@SolomonRutzky该字段的排序规则是'SQL_Latin1_General_CP1_CI_AS'–
Eric

Answers:


17

在任何情况下,SQL Server都不存储UTF-8。您可以通过NVARCHAR(包括NCHARNTEXT,但不要使用NTEXT)和通过UTF-16 Little Endian(LE)XML,或通过代码页面通过VARCHAR(包括CHARTEXT,但不要使用TEXT)获得一些8位编码。。

这里的问题是您的代码错误地转换了0x82字符,以为它是UTF-8,但事实并非如此。没有值0x82的UTF-8“字符”,这就是为什么您会得到“未知” /替换符号“ ...”的原因。请参阅下面的UTF-8表,该表显示0x82的单字节没有字符:

UTF-8编码表

如OP所述,相关列的排序规则为SQL_Latin1_General_CP1_CI_AS,这表示8位编码使用的是代码页1252,即Windows Latin 1(ANSI)。并且检查该图表(向下滚动到底部的图表,因为它具有字符名称)的值0x82(在“代码点”列中查找“ 82”)实际上是您在SSMS中看到的单个低9引号。在UTF-8中,该字符是3个字节的序列:E2 80 9A

所有这些意味着:您的Python代码需要将SQL Server连接的客户端编码设置为Code Page 1252,或者需要将返回的字符串的编码 Code Page 1252 更改/转换 UTF-8。

当然,如果正在网页上显示该字符,则可以将页面的声明字符集更改为Windows-1252,但是如果已经有UTF-8字符,则可能会干扰页面上的其他字符。


很好,这非常有帮助,谢谢所罗门。请让我知道翻译错误。这是一个非常棘手的问题,我什至不知道从哪里开始。
艾瑞克(Eric)

哇,@ Solomon令人惊讶的细节!我在这里寻找另一个Python + MS SQL问题,但由于我学到了很多东西,所以继续阅读。:-P
Mike Williamson

1
@MikeWilliamson感谢您的赞美:)。您可能也对以下内容感兴趣:与C#.NET md5(在SO上)不同的TSQL md5哈希(在SO上),如何剥离希伯来语重音标记(在DBA.SE上位于此处)和Collat​​ions.Info。请享用!
所罗门·鲁茨基

谢谢!我怀疑任何人与基于非拉丁语言的工作知道这个东西远远比我们任何人在美国/英国幸福的工作。:)
Mike Williamson

1
只需注意:MS SQL Server 2019在VARCHAR / CHAR数据类型中引入了对UTF-8的本机支持。
格雷戈里·阿雷纽斯
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.