【问题标题】:Unicode issue with PyODBC queryPyODBC 查询的 Unicode 问题
【发布时间】:2018-02-09 09:15:58
【问题描述】:

我在使用 PyODBC 查询我的 MSSQL 服务器时遇到问题。

我相信的原因是我有使用 unicode 命名的列。这些列来自我的主数据中的单个列。

有问题的列是“afkastningsgrad_primær_drift”

知道如何运行此查询吗? (由于我没有服务器所有权,因此无法在服务器上构建视图并重命名列)

SQL:

WITH dataTable AS (
    SELECT 
        KredsEjdNr, Navn, Vaerdi
    FROM qryEjendomsData

    WHERE 
        RegnskabsAar = 2016 
        AND Projekt = 1710
        AND Navn IN (
            'ekm_ko' , 'afkastningsgrad_primær_drift', 'fremst_pris_maelk'
        )
    GROUP BY KredsEjdNr, Navn, Vaerdi
), 
pivotData AS (

    SELECT * 
    FROM dataTable
    PIVOT
        (
            SUM(Vaerdi)
            FOR[Navn] IN (
                [ekm_ko], [afkastningsgrad_primær_drift], [fremst_pris_maelk]
            )
        )
    AS pivotTable
)

SELECT 
    CAST([KredsEjdNr] AS NVARCHAR) AS [kredsEjdNr], 
    CAST(ekm_ko AS int) AS [EKM pr ko],
    [afkastningsgrad_primær_drift] as [Afkastningsgrad],
    [fremst_pris_maelk] AS [Fremstillingspris pr. kg EKM]
 from pivotData
 where [ekm_ko] IS NOT NULL and [fremst_pris_maelk] IS NOT NULL
 order by kredsEjdNr

Python 代码:

#!/usr/local/bin/python
# -*- coding: utf-8 -*-
connectionstring = 'DRIVER={SQL Server Native Client 11.0};SERVER=server;DATABASE=database;UID=%s;PWD=%s' %(usr,pswd)
conn = pyodbc.connect(connectionstring)
cursor = conn.cursor()
dataList = cursor.execute(unicode(sql)).fetchall()

错误:

Traceback(最近一次调用最后一次):文件“data.py”,第 84 行,在 dataList = cursor.execute(unicode(sql)).fetchall() UnicodeDecodeError: 'ascii' codec can't decode byte 0xc3 in position 183:序数不在范围内(128)

【问题讨论】:

  • 嗯必须对我的查询进行 .decode('utf-8) 才能使其工作,有一段时间没有这样做了......
  • 您使用的是哪个pyodbc.version
  • 我使用的是 4.0.16 版

标签: python sql-server unicode pyodbc


【解决方案1】:

问题不在于列名中的 Unicode 字符,而在于 Python2 下 str 变量中的非 ASCII 字节。当 pyodbc .execute 调用以 str 形式接收命令文本时,它会尝试使用默认编码(对于 Python2 为“ascii”)对其进行处理。

以下测试代码

# -*- coding: utf-8 -*-
import sys
print("sys.getdefaultencoding() is '{0}'".format(sys.getdefaultencoding()))
import pyodbc

cnxn = pyodbc.connect("DSN=SQLmyDb", autocommit=True)
crsr = cnxn.cursor()

# setup test environment
crsr.execute(u"CREATE TABLE #tmp (afkastningsgrad_primær_drift INT)")
crsr.execute(u"INSERT INTO #tmp VALUES (1)")

print('')
print('Test_1: "SELECT * ..." as str')
sql = "SELECT * FROM #tmp"
print("  sql: " + repr(sql))
crsr.execute(sql)
print("    column name from result set: " + repr(crsr.description[0][0]))

print('')
print('Test_2: "SELECT colname ..." as str')
sql = "SELECT afkastningsgrad_primær_drift FROM #tmp"
print("  sql: " + repr(sql))
try:
    crsr.execute(sql)
    print("    OK")
except UnicodeDecodeError as ude:
    print("    UnicodeDecodeError: " + str(ude))

print('')
print('Test_3: "SELECT colname ..." as unicode')
sql = sql.decode('utf-8')
print("  sql: " + repr(sql))
try:
    crsr.execute(sql)
    print("    OK")
except Exception as ex:
    print("    Exception: " + str(ex))

cnxn.close()

生产

sys.getdefaultencoding() is 'ascii'

Test_1: "SELECT * ..." as str
  sql: 'SELECT * FROM #tmp'
    column name from result set: u'afkastningsgrad_prim\xe6r_drift'

Test_2: "SELECT colname ..." as str
  sql: 'SELECT afkastningsgrad_prim\xc3\xa6r_drift FROM #tmp'
    UnicodeDecodeError: 'ascii' codec can't decode byte 0xc3 in position 27: ordinal not in range(128)

Test_3: "SELECT colname ..." as unicode
  sql: u'SELECT afkastningsgrad_prim\xe6r_drift FROM #tmp'
    OK

Test_1 显示带有 Unicode 字符的列名正确地返回为 unicode 对象。

Test_2 显示默认 Python2 编码 ('ascii') 在包含大于 0x7F 的 UTF-8 字节的 str 上阻塞。

Test_3 表明,如果我们使用 .decodestr(包含 UTF-8 字节)转换为适当的 unicode 对象,然后我们将其传递给 .execute 方法,则不会发生错误。

【讨论】:

  • 如果您使用 UTF-8,Python 3 将使您的生活变得轻松很多。 :)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-06-07
  • 2012-12-25
  • 2023-03-23
  • 1970-01-01
  • 2014-12-24
相关资源
最近更新 更多