2017-08-31 105 views
2

我無法使用PyODBC查詢我的MSSQL服務器。PyODBC查詢的Unicode問題

我相信的原因是我有使用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 (most recent call last): File "data.py", line 84, in dataList = cursor.execute(unicode(sql)).fetchall() UnicodeDecodeError: 'ascii' codec can't decode byte 0xc3 in position 183: ordinal not in range(128)

+0

嗯,必須.decode('utf-8)我的查詢,使其工作,有沒有這樣做了一段時間... –

+1

你使用哪個'pyodbc.version'? –

+0

使用4.0.16版的Im –

回答

2

問題不在列名中使用Unicode字符,而使用非ASCII 字節str變量在Python2下。當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顯示str上包含UTF-8字節大於0x7F的默認Python2編碼('ascii')扼流圈。

Test_3表明,如果我們使用.decodestr(含有UTF-8字節)轉換成一個適當的unicode對象,我們然後傳遞給.execute方法不會發生錯誤。

+1

如果你使用的是UTF-8,Python 3會讓你的生活更加輕鬆。 :) – FlipperPA