我在Ubuntu 11.10 32位上使用Python 2.7.2(unixODBC 2.2.14,pyodbc 2.1.11和mdbtools驱动程序)尝试读取Microsoft Access数据库(JET 4 .mdb)时遇到了一些问题。是的,我知道这是一个可怕的想法,但奇怪的是,这是我能找到的最简单的解决方案。我想避免由于各种原因将.mdb数据库转换为另一种格式(如sqlite),但似乎这可能是唯一的解决方案,如果我无法解决这个问题。我为这个问题的长度道歉,而且我对linux和odbc /数据库处理也很陌生。我花了3天的时间试图解决这个问题,但最后两个都没有。
问题:我可以读取数据库,但这些值没有正确编码/格式化。
Python代码:
import pyodbc
connection=pyodbc.connect('DSN=dbcon_test') # Driver = /usr/lib/libmdbodbc.so.0
cursor=connection.cursor()
cursor.execute('SELECT * FROM FIELDNOTES')
rows=cursor.fetchone()
输出:
行:
('03/14/03', 49, 49, None, 'visit\x00\xfd', None, 'upstream of ', 942815025)
应该是:
('03/14/03 15:40:00, 1, 1, None, 'visit', None, 'upstream of road, just below small drop, 1728)
我认为并且一直在努力弄清楚的是,在读取列信息(SQLDescribeCol.c)和/或获取数据时(SQLFetch.c和SQLGetData.c)存在错误。
以第1列和第2列为例。第1列是时间戳,并正确识别(SQL_TYPE_TIMESTAMP)。它还将正确的值读入缓冲区(Buffer = [03/14/03 15:40:00]),但似乎被Column Size / StrLen Or Ind缩短为8,因为结果输出长度为8个字符'03 / 14/03',虽然我认为大小8是指字节(?)。
第2列是整数值1,但在缓冲区中它被读为49.我还没弄清楚为什么,但它读取所有整数值为ascii代码/数字字符(1变为49,2变为50等),其中相当不方便,当数量变大时我不知道如何处理这个问题(例如1728变为942815025)。缓冲区中也会读取双数字。
来自日志,第1列和第2列的SQLDescribeCol(与下面链接的完整日志文件中的相同):
[ODBC][16118][1320928843.731400][SQLDescribeCol.c][243]
Entry:
Statement = 0xa0e1ab0
Column Number = 1
Column Name = 0xbffd2820
Buffer Length = 300
Name Length = (nil)
Data Type = 0xbffd281a
Column Size = 0xbffd2814
Decimal Digits = 0xbffd281c
Nullable = 0xbffd281e
[ODBC][16118][1320928843.731411][SQLDescribeCol.c][493]
Exit:[SQL_SUCCESS]
Column Name = [Date/Time]
Data Type = 0xbffd281a -> -1
Column Size = 0xbffd2814 -> 8
Decimal Digits = 0xbffd281c -> 0
Nullable = 0xbffd281e -> 0
[ODBC][16118][1320928843.731423][SQLDescribeCol.c][243]
Entry:
Statement = 0xa0e1ab0
Column Number = 2
Column Name = 0xbffd2820
Buffer Length = 300
Name Length = (nil)
Data Type = 0xbffd281a
Column Size = 0xbffd2814
Decimal Digits = 0xbffd281c
Nullable = 0xbffd281e
[ODBC][16118][1320928843.731434][SQLDescribeCol.c][493]
Exit:[SQL_SUCCESS]
Column Name = [Site]
Data Type = 0xbffd281a -> 4
Column Size = 0xbffd2814 -> 4
Decimal Digits = 0xbffd281c -> 0
Nullable = 0xbffd281e -> 0
日志列1和2中的SQLGetData:
[ODBC][16118][1320928843.732565][SQLGetData.c][233]
Entry:
Statement = 0xa0e1ab0
Column Number = 1
Target Type = 1 SQL_CHAR
Buffer Length = 1024
Target Value = 0xbffd24dc
StrLen Or Ind = 0xbffd24d8
[ODBC][16118][1320928843.732584][SQLGetData.c][497]
Exit:[SQL_SUCCESS]
Buffer = [03/14/03 15:40:00]
Strlen Or Ind = 0xbffd24d8 -> 8
[ODBC][16118][1320928843.732595][SQLGetData.c][233]
Entry:
Statement = 0xa0e1ab0
Column Number = 2
Target Type = 4 SQL_INTEGER
Buffer Length = 4
Target Value = 0xbffd2950
StrLen Or Ind = 0xbffd295c
[ODBC][16118][1320928843.732606][SQLGetData.c][497]
Exit:[SQL_SUCCESS]
Buffer = [49]
Strlen Or Ind = 0xbffd295c -> 4
这些是mdbtools提供的表格的列:
mdb-schema database.mdb -T FIELDNOTES
( [Size from MDB Viewer]
Date/Time DateTime (Short), 8
Site Long Integer, 4
Note_ID Long Integer, 4
Sampler Text (100), 100
Action Text (100), 100
Instrument ID Long Integer, 4
Memo Memo/Hyperlink (255), 0
Note_AutoID Long Integer 4
);
完整的ODBC日志文件:http://pastebin.com/Q01ahwCW
如果有人有任何关于如何解决此问题的提示(包括简单的数据库转换,因为如果我这样做,我必须经常转换),我们将不胜感激!如果需要更多信息,我可以提供!
谢谢!