Python 3.6向SQL Server的varbinary(max)列插入bytes数据异常问题排查
解决Python插入bytes到SQL Server varbinary(max)列值不正确的问题
我来帮你捋清楚问题出在哪——你现在遇到的情况是,把字符串形式的十六进制当成字节数据直接存了,导致数据库里的内容是原字符串的字符编码,而不是你想要的十六进制对应的字节。
问题根源
你Python里的VBM是b'0x443611119900554616035D15220',这本质是一个字节串形式的文本,内容是0x443611119900554616035D15220这个字符串。当你调用VBM.encode('utf-8')时,相当于把这个文本里的每个字符都转换成对应的ASCII字节:比如'0'对应0x30,'x'对应0x78,'4'对应0x34……所以数据库里看到的0x307834353143313131313936303...,其实就是这些字符的字节组合,完全不是你想要的十六进制对应的原始字节。
正确的解决方法
你需要把这个十六进制字符串(去掉0x前缀)解析成真正的bytes对象,而不是把字符串本身转成字节。具体步骤如下:
- 先把字节串形式的VBM转换成普通字符串,去掉开头的
0x前缀 - 使用
bytes.fromhex()方法,将纯十六进制字符串转换成对应的字节数据 - 把转换后的字节数据传入SQL语句执行插入
修改后的代码示例:
cn = pyodbc.connect() cr = cn.cursor() script = """INSERT INTO table (Col1, col2) VALUES (?, ?)""" # 处理VBM:先转成字符串,去掉0x前缀 vbm_str = VBM.decode('utf-8').lstrip('0x') # 将十六进制字符串转为真实的bytes vbm_bytes = bytes.fromhex(vbm_str) values = (vbm_bytes, FN) cr.execute(script, values) cn.commit()
排查方向建议
- 确认VBM的类型:先打印
type(VBM),如果是str类型,直接去掉0x前缀即可;如果是bytes类型,要先decode成字符串再处理 - 验证转换后的字节:插入前打印
vbm_bytes,确认是否是你预期的字节(比如原十六进制对应的二进制数据) - 正确查看数据库内容:在SQL Server中查看varbinary列时,用
CONVERT(varchar(max), Col1, 2)把列值转成十六进制字符串,对比是否和原VBM的十六进制一致;或者在SSMS中右键列值选择“以十六进制显示” - 检查依赖版本:确保pyodbc版本兼容Python3.6和你的SQL Server版本,推荐使用pyodbc 4.0.28及以上的稳定版本
内容的提问来源于stack exchange,提问作者Akshay




