背景
在对接国内一些早期开发的 ERP、物流、一卡通等系统时,SQL Server 数据库中的中文数据常常采用 GBK 编码 存储。
然而 pymssql 在连接时若使用 charset='utf8',读取出来的中文字符会呈现为"乱码"------实际上是 UTF-8 解码 GBK 字节导致的现象。
直接修改连接字符集为 charset='gbk' 又可能引发其他字段(如数字、英文、特殊符号)的异常,甚至导致连接失败。
本文将结合真实案例,提供一个 稳定、可复现 的乱码修复方案。
问题现象
某物流系统数据库,表结构如下:
CREATE TABLE t_record (
s_vehicle_no VARCHAR(50), -- 车牌号(中文)
s_remark VARCHAR(200), -- 备注(中文)
...
);
使用 pymssql 查询结果:
{
'车牌号': '沪A12345', # 实际应为"沪A12345"
'备注': 'å
è£
æå' # 实际应为"包装损坏"
}
这类乱码特征明显:英文字符正常,中文字符变为多字节乱码。
错误尝试
1. 直接修改连接字符集
DB_CONFIG = {
'charset': 'gbk'
}
结果:
-
某些字符集下查询报错(如
UnicodeDecodeError) -
数字、英文可能被错误转换
-
与
pymssql内部处理机制不兼容
2. 手动 encode/decode
value.encode('latin-1').decode('gbk')
有效,但需要明确区分哪些字段是中文、哪些不是,无法通用。
最终解决方案
核心思路
统一使用 charset='utf8' 连接 ,在读取后将所有字符串字段通过 "拉丁-1 中转" 方式还原为 GBK 原始字节,再解码为正确的中文。
原理说明
-
pymssql在utf8连接模式下,将数据库返回的字节流按 UTF-8 解码。 -
若数据库实际存储为 GBK,则会被错误解码成"假 Unicode 字符串"。
-
修复过程:
-
将该字符串按
latin-1(单字节无损编码)转回原始字节 -
用
GBK重新解码 -
得到真实中文
import pymssql
def fix_gbk_text(text):
"""修复 pymssql + utf8 模式下的 GBK 乱码"""
if text is None or not isinstance(text, str):
return text
try:
return text.encode('latin-1').decode('GBK')
except:
return textdef get_clean_data(order_no):
conn = pymssql.connect(
server='192.168..',
user='',
password='',
database='******',
charset='utf8'
)
cursor = conn.cursor(as_dict=True)sql = """ SELECT TOP 1 s_vehicle_no AS 车牌号, s_remark AS 备注 FROM t_record WHERE s_code = %s """ cursor.execute(sql, (order_no,)) row = cursor.fetchone() if row: clean_row = {} for key, value in row.items(): if isinstance(value, str): clean_row[key] = fix_gbk_text(value) else: clean_row[key] = value return clean_row else: return None -
验证结果
修复前:
{
'车牌号': '沪A12345',
'备注': 'å
è£
æå'
}
修复后:
{
'车牌号': '沪A12345',
'备注': '包装损坏'
}
适用场景
该方案适用于以下情况:
-
SQL Server 数据库,中文采用 GBK / GB2312 / GB18030 编码
-
使用
pymssql且无法修改数据库端编码 -
需要同时保留数字、英文、Decimal、日期等非字符串类型的原始格式
注意事项
-
仅修复字符串字段:数字、布尔值、Decimal 等类型无需处理,直接保留。
-
性能影响极小:仅在查询结果集上做一次遍历修复,适合中小规模数据。
-
兼容性好:修复失败的字段会返回原值,不会导致程序崩溃。
-
适用于多表 JOIN:无论多少字段,统一遍历修复即可。
总结
在国内企业信息化系统中,GBK 编码的中文数据库依然广泛存在。
pymssql 默认的 UTF-8 连接方式虽然保证了跨平台兼容性,但在处理老系统数据时容易出现乱码。
本文提供了一种 无侵入、易封装、可复用 的修复模式,能够在不修改数据库、不改变连接配置的前提下,干净地还原真实中文数据。
该方案已在实际生产环境中稳定运行,适用于各类 GBK 编码的中文数据提取场景。