views:

1430

answers:

6

I am using pyodbc, via Microsoft Jet, to access the data in a Microsoft Access 2003 database from a Python program.

The Microsoft Access database comes from a third-party; I am only reading the data.

I have generally been having success in extracting the data I need, but I recently noticed some discrepancies.

I have boiled it down to a simple query, of the form:

SELECT field1 FROM table WHERE field1 = 601 AND field2 = 9067

I've obfuscated the field names and values but really, it doesn't get much more trivial than that! When I run the query in Access, it returns one record.

Then I run it over pyodbc, with code that looks like this:

connection = pyodbc.connect(connectionString)
rows = connection.execute(queryString).fetchall()

(Again, it doesn't get much more trivial than that!)

The value of queryString is cut-and-pasted from the working query in Access, but it returns no records. I expected it to return the same record.

When I change the query to search for a different value for field2, bingo, it works. It is only some values it rejects.

So, please help me out. Where should I be looking next to explain this discrepancy? If I can't trust the results of trivial queries, I don't have a chance on this project!

Update: It gets even simpler! The following query gives different numbers...

SELECT COUNT(*) FROM table

I ponder if it is related to some form of caching and/or improper transaction management by another application that occasionally to populates the data.

+1  A: 

can you give us an obfuscated database that shows this problem? I've never experienced this. At least give the table definitions -- are any of the columns floats or decimal?

Aaron Watters
I've voted you up for the suggestion of checking for floats. Good thinking, however that's not the problem, as the updated version reveals with no WHERE clause.I am working on how to get a table description out of Access for you.
Oddthinking
+1  A: 

This might sound stupid. But...

Is the path to actual database & connection string (DSN) point to same file location?

shahkalpesh
That's a perfectly reasonable suggestion; I really hope it turns out to be something as trivial as that!I have double-checked, and they both point to the same directory. I have seen Access 2003 get confused and apparently open a recent MDB file that had since been deleted, so I still wonder if there is some caching or similar happening here.
Oddthinking
Is the MDB file on a network path, that you are trying to use using a python based application on the machine?
shahkalpesh
+1  A: 

Do you have the same problem with other ODBC tools, for example Query Tool? You can also turn on ODBC tracing in ODBC Connection Manager. I don't have access and don't know whether its sql commands will be traced but sometimes it helps me to solve ODBC problems.

Michał Niklas
I just installed Query Tool. I had to specify the data-source in a different way (not a connection string). I ran "SELECT COUNT(*) FROM table". It gave me the same answer as my Python code, and a different (smaller) answer to the same statement in Access. So, good news, it isn't my Python code or pyodbc. Bad news: I can't trust Access/ODBC.
Oddthinking
Access is a really cool tool, but it is buggy. For example sometimes if you write a query in SQL and edit it later, it will tell you you have syntax errors that your corrected -- you have to copy the query into notepad and back into a fresh Access sql design view. It doesn't seem like Access is getting better to me, just more confusing and complicated.
Aaron Watters
Is Access in use in this question? So far as I can tell, only Jet is being used, so the Access QBE isn't involved.
David-W-Fenton
+1  A: 

Are the fields indexed? If so, maybe one of the indexes is corrupted and you need to compact the MDB file. If an index is corrupt, it can lead to major issues. You could lose existing relationships (if the corrupt index is the PK), or you could lose data. So you need to have a backup before you do this. If there is a corrupt index, I think the interactive Access compact operation will tell you, but if not, you can look for the MSysCompactErrors table which will tell you what errors occurred during the compact.

This happens only very rarely and can indicate one of two things:

  1. bad application design, including obsolete Jet versions (Jet 4 before service pack 6 was very susceptible to this, and that's where I encountered it).

  2. unreliable operating environment (networking/hardware/software).

Of course, this suggestion is a real long shot, but it is definitely one cause of different results (the most common would be to ORDER BY on the corrupt index and you'll end up with a different record count than with another ORDER BY).

David-W-Fenton
I will check this out. My first step was to check my JET version. I am running the very latest version, which came with Vista Service Pack 1. (http://support.microsoft.com/kb/239114 was my reference.)
Oddthinking
A: 

Problem was resolved somewhere between an upgrade to Access 2007 and downloading a fresh copy of the database from the source. Still don't know what the root cause was, but suspect some form of index corruption.

Oddthinking
+1  A: 

I guess the problem may be that you did not commit the query. PYODBC starts with autocommit = False and therefore every query like select,insert,update etc will start a transaction that in order to get effect you have to commit. Either call connection.autocommit = True or call cursor.execute("commit") after the query and then fetchall.

Piotr Jakubowski
You even have to commit SELECT statements?
David-W-Fenton
I don't know about Access Database but if you are using SQL Server then havin autocommit = False means having implicit transactions. http://msdn.microsoft.com/en-us/library/ms188317.aspx states that even SELECT starts a transaction.
Piotr Jakubowski