У меня возникают некоторые проблемы при попытке чтения базы данных Microsoft Access (JET 4 .mdb) с использованием Python 2.7.2 (unixODBC 2.2.14, pyodbc 2.1.11 и драйвера mdbtools) в 32-разрядной версии Ubuntu 11.10. Да, я знаю, что это ужасная идея, но, как ни странно, это самое простое решение, которое я мог найти. Я хочу избежать преобразования базы данных .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, но в буфере он читается как 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
SQLGetData из столбцов журнала 1 и 2:
[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
Если у кого-нибудь есть какие-либо советы, как решить эту проблему (включая простое преобразование базы данных, поскольку мне пришлось бы преобразовывать очень часто, если бы я это сделал), это было бы очень признательно! Если потребуется дополнительная информация, я могу это предоставить!
Спасибо!