我在尝试在 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 或 Ind 缩短为 8,因为结果输出为 8 个字符长 '03 /14/03',虽然我认为大小 8 指的是字节(?)。
第 2 列是整数值 1,但在 Buffer 中读取为 49。我还没有弄清楚为什么,但它将所有整数值读取为 ascii 代码/数字字符(1 变为 49,2 变为 50 等),这相当不方便当数字变大时(例如1728变成942815025),我不知道如何处理。双数在缓冲区中也被错误地读取。
SQLDescribeCol 来自日志,第 1 列和第 2 列(与下面链接的完整日志文件相同):
[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 给出的表 abd 的列:
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
如果有人对如何解决这个问题有任何提示(包括简单的数据库转换,因为我必须经常转换),将不胜感激!如果需要更多信息,我可以提供!
谢谢!