从pyodbc到MS-SQL的编码调用

2024-09-27 21:34:24 发布

您现在位置:Python中文网/ 问答频道 /正文

我使用pyodbc模块通过SQL Alchemy连接到MS-SQL服务器。一切似乎都很好,直到我开始有问题的编码。一些非ascii字符将被替换为“?”

数据库有一个排序规则“Latin1_General_CI_AS”(我也检查了特定字段,它们保持相同的排序规则)。我开始在create_engine的调用中选择编码“latin1”,这似乎适用于西欧字符(如法语或西班牙语,如é),但不适用于东欧字符。具体来说,我对字符ć有问题

我一直在尝试选择其他编码as stated on Python documentation,特别是微软的编码,比如cp1250cp1252,但我一直面临同样的问题。

有人知道如何解决这些分歧吗?排序规则“Latin1_General_CI_AS”是否与Python编码相同?

我当前连接的代码如下

for sqlalchemy import *

def connect():
    return pyodbc.connect('DSN=database;UID=uid;PWD=password')

engine = create_engine('mssql://', creator=connect, encoding='latin1')
connection = engine.connect()

澄清和评论:

  • 从数据库检索信息时会出现此问题。我不需要储存任何东西。
  • 一开始我没有指定编码,结果是,每当在数据库上遇到非ascii字符时,pyodbc就会引发UnicodeDecodeError。我更正了使用“latin1”作为编码,但这并不能解决所有字符的问题。
  • 我承认服务器不在latin1上,评论不正确。我一直在检查数据库排序规则和特定字段排序规则,似乎都在“Latin1_General_ciu AS”中,那么,如何存储ć?也许我没有正确理解校勘。
  • 我稍微修正了一下这个问题,特别是,我尝试了比latin1更多的编码,还有cp1250cp1252(根据msdn的说法,这显然是用于“拉丁语通用词”的编码)

更新:

好,按照这些步骤,我得到DB使用的编码似乎是cp1252:http://bytes.com/topic/sql-server/answers/142972-characters-encoding 无论如何,这似乎是一个坏的假设,反映在答案上。

更新2: 无论如何,在正确配置odbc驱动程序之后,我不需要在Python代码上指定编码。


Tags: 服务器数据库编码sql排序规则asconnect
3条回答

尝试使用pyodbc.connect()参数convert_unicode=True连接到数据库,例如从sqlalchemy:

engine = create_engine('mssql://yourdb', connect_args={'convert_unicode': True})

这应该确保您得到的所有结果(而不仅仅是来自nvarchar等的结果)都是unicode,正确地从数据库中使用的任何编码转换而来。

至于写入数据库,请始终使用unicode。如果我没有弄错(稍后会检查),pyodbc将确保它也能正确地写入数据库。

(当然,如果数据库使用的编码不支持要写入的字符,则仍然会出现错误:如果希望列支持任何类型的字符,则还必须在数据库上使用unicode列)

您应该停止使用代码页并切换到Unicode。这是解决这类问题的唯一方法。

原始评论变成了答案:

cp1250和cp1252不是“拉丁编码”。排序规则不是编码。回复:谁说“服务器是用拉丁语编码的”?如果服务器希望所有输入/输出都用拉丁语1编码(我对此表示怀疑),那么您就很难将一些东欧字符输入到数据库中(俄语、汉语、希腊语等)。

更新

你需要看得比校勘更远些msdn.microsoft.com/en-us/library/ms174596(v=SQL.90)。aspx建议,对于Latin1_-General_-CI_,因为使用的编码是cp1252“”,所以是codswallop。该表为每个区域设置提供一个LCID(区域设置ID)、默认值排序规则和代码页。是的,排序规则“Latin1_General_CI_AS”与多个地区的cp1252代码页关联列出。对于两个地区(亚美尼亚语和格鲁吉亚语),它与“Unicode”代码页(!!!)关联列出。

很简单,您需要了解数据库使用的代码页是什么。

尝试从数据库中提取数据而不指定任何编码。不要费心编码,不管你猜你的控制台可能在使用什么编码——这只会增加另一个混乱的来源。相反,使用print repr(data)。在这里报告您从repr()中获得的信息,在这里您需要非拉丁字符。

相关问题 更多 >

    热门问题