2009-05-06 8 views
3

J'utilise pyodbc, via Microsoft Jet, pour accéder aux données d'une base de données Microsoft Access 2003 à partir d'un programme Python.PyODBC et Microsoft Access: Résultats incohérents d'une requête simple

La base de données Microsoft Access provient d'un tiers; Je ne fais que lire les données.

J'ai généralement réussi à extraire les données dont j'ai besoin, mais j'ai récemment remarqué quelques divergences.

J'ai fait bouillir vers le bas à une simple requête, de la forme:

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

J'ai obscurcie les noms des champs et des valeurs, mais vraiment, il ne va pas beaucoup plus trivial que cela! Lorsque j'exécute la requête dans Access, il renvoie un enregistrement.

Puis je l'exécuter sur pyodbc, avec le code qui ressemble à ceci:

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

(Encore une fois, il ne va pas beaucoup plus trivial que ça!)

La valeur de queryString est coupée -et-collé à partir de la requête de travail dans Access, mais il renvoie aucun enregistrements. Je m'attendais à ce qu'il retourne le même disque.

Lorsque je change la requête pour rechercher une valeur différente pour field2, bingo, cela fonctionne. Ce sont seulement certaines valeurs qu'il rejette.

Alors, aidez-moi s'il vous plaît. Où devrais-je regarder pour expliquer cette divergence? Si je ne peux pas faire confiance aux résultats de requêtes triviales, je n'ai aucune chance sur ce projet!

Mise à jour: Cela devient encore plus simple! La requête suivante donne des chiffres différents ...

SELECT COUNT (*) FROM table

je médite si elle est liée à une certaine forme de mise en cache et/ou une mauvaise gestion des transactions par une autre application que, parfois, à des données renseigne la .

+0

Si vous avez un objet curseur là-bas pour exécuter la chaîne de requête? Fetchall serait alors appelé sur le curseur pour produire des lignes. Voir http://code.google.com/p/pyodbc/wiki/Rows – barrowc

+0

@barrowc, Intéressant. Je n'ai pas remarqué l'absence d'un appel de curseur(). Je suis sûr que j'ai copié ceci d'un exemple quelque part. J'ai essayé de l'ajouter dans [rows = connection.cursor(). Execute (queryString) .fetchall()] mais cela ne faisait aucune différence - apparemment pyodbc est plus tolérant que la spécification de l'API DB Python. – Oddthinking

Répondre

1

Le problème a été résolu quelque part entre une mise à niveau vers Access 2007 et le téléchargement d'une nouvelle copie de la base de données à partir de la source. Je ne sais toujours pas quelle était la cause première, mais je soupçonne une forme de corruption d'index.

1

pouvez-vous nous donner une base de données obfuscated qui montre ce problème? Je n'ai jamais vécu ça. Au moins donner les définitions de la table - est-ce que l'une des colonnes est flottante ou décimale?

+0

Je vous ai voté pour la suggestion de vérifier les flotteurs. Bonne réflexion, mais ce n'est pas le problème, comme le révèle la version mise à jour sans clause WHERE. Je travaille sur la façon d'obtenir une description de table hors d'accès pour vous. – Oddthinking

1

Cela peut sembler stupide. Mais ...

Le chemin vers la base de données & pointe-t-il vers le même emplacement de fichier?

+0

C'est une suggestion parfaitement raisonnable; J'espère vraiment que ça va être quelque chose d'aussi trivial que ça! J'ai vérifié deux fois, et tous deux pointent vers le même répertoire. J'ai vu Access 2003 se confondre et apparemment ouvrir un fichier MDB récent qui a été supprimé depuis, donc je me demande toujours s'il y a un cache ou quelque chose de similaire qui se passe ici. – Oddthinking

+0

Le fichier MDB est-il un chemin réseau que vous essayez d'utiliser à l'aide d'une application basée sur python sur la machine? – shahkalpesh

1

Avez-vous le même problème avec d'autres outils ODBC, par exemple Query Tool? Vous pouvez également activer le suivi ODBC dans ODBC Connection Manager. Je n'ai pas accès et je ne sais pas si ses commandes sql seront tracées mais parfois cela m'aide à résoudre des problèmes ODBC.

+0

Je viens d'installer l'éditeur de requêtes. J'ai dû spécifier la source de données d'une manière différente (pas une chaîne de connexion). J'ai couru "SELECT COUNT (*) FROM table". Il m'a donné la même réponse que mon code Python, et une réponse différente (plus petite) à la même déclaration dans Access. Donc, bonne nouvelle, ce n'est pas mon code Python ou pyodbc. Mauvaise nouvelle: je ne peux pas faire confiance à Access/ODBC. – Oddthinking

+0

L'accès est un outil vraiment cool, mais il est buggé. Par exemple, si vous écrivez une requête en SQL et que vous l'éditez plus tard, il vous dira que vous avez des erreurs de syntaxe que vous avez corrigées - vous devez copier la requête dans le bloc-notes et la redessiner. Il ne semble pas qu'Access m'améliore, mais plutôt plus confus et compliqué. –

+0

L'accès est-il utilisé dans cette question? Pour autant que je sache, seul Jet est utilisé, donc Access QBE n'est pas impliqué. –

1

Les champs sont-ils indexés? Si c'est le cas, l'un des index est peut-être corrompu et vous devez compacter le fichier MDB. Si un index est corrompu, cela peut entraîner des problèmes majeurs. Vous pourriez perdre des relations existantes (si l'index corrompu est le PK), ou vous pourriez perdre des données. Vous devez donc avoir une sauvegarde avant de faire cela.S'il existe un index corrompu, je pense que l'opération interactive Access compact vous le dira, mais si ce n'est pas le cas, vous pouvez rechercher la table MSysCompactErrors qui vous indiquera quelles erreurs se sont produites pendant le compactage.

Cela ne se produit que très rarement et peut indiquer l'une des deux choses:

  1. mauvaise conception d'applications, y compris obsolètes versions Jet (Jet 4 avant Service Pack 6 a été très sensible à cela, et c'est là que je rencontrais il).

  2. environnement d'exploitation non fiable (réseau/matériel/logiciel).

Bien sûr, cette suggestion est un vrai coup long, mais il est certainement une cause de résultats différents (serait le plus commun est à l'ordre par l'indice corrompu et vous finirez avec un autre dossier compter qu'avec un autre ORDER BY).

+0

Je vais vérifier cela. Ma première étape a été de vérifier ma version JET. Je suis la dernière version, qui est venu avec Vista Service Pack 1. (http://support.microsoft.com/kb/239114 était ma référence.) – Oddthinking

1

Je suppose que le problème peut être que vous n'avez pas validé la requête. PYODBC commence par autocommit = False et par conséquent chaque requête comme select, insert, update etc. lancera une transaction qui, pour obtenir l'effet que vous avez à valider. Appelez connection.autocommit = True ou appelez cursor.execute("commit") après la requête, puis fetchall.

+0

Vous avez même besoin de valider les instructions SELECT? –

+0

Je ne connais pas la base de données Access, mais si vous utilisez SQL Server, havin autocommit = False signifie avoir des transactions implicites. http://msdn.microsoft.com/en-us/library/ms188317.aspx indique que même SELECT démarre une transaction. –

Questions connexes