Question

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.

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é certaines divergences.

Je l'ai résumé à une simple requête, de la forme:

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

J'ai obscurci les noms et les valeurs des champs, mais en réalité, cela n’est pas plus trivial! Lorsque j'exécute la requête dans Access, il renvoie un enregistrement.

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

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

(Encore une fois, ça ne devient pas plus trivial que ça!)

La valeur de queryString est copiée-collée à partir de la requête de travail dans Access, mais elle renvoie des enregistrements no . Je m'attendais à ce qu'il retourne le même enregistrement.

Lorsque je modifie la requête pour rechercher une valeur différente pour field2, bingo, cela fonctionne. Ce ne sont que quelques valeurs qu’il rejette.

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

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

SELECT COUNT (*) FROM table

Je me demande s'il est lié à une forme de mise en cache et / ou à une gestion incorrecte des transactions par une autre application qui remplit parfois les données.

Était-ce utile?

La solution 5

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 connais toujours pas la cause du problème, mais nous soupçonnons une forme de corruption d'index.

Autres conseils

pouvez-vous nous donner une base de données masquée qui montre ce problème? Je n'ai jamais vécu ça. Donnez au moins les définitions de table - y a-t-il des colonnes flottantes ou décimales?

Cela peut sembler stupide. Mais ...

Est-ce le chemin de la base de données actuelle & amp; chaîne de connexion (DSN) pointe vers le même emplacement de fichier?

Avez-vous le même problème avec d'autres outils ODBC, par exemple l’ outil de requête ? Vous pouvez également activer le suivi ODBC dans le gestionnaire de connexions ODBC. 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 les problèmes ODBC.

Les champs sont-ils indexés? Si tel est le cas, l'un des index est peut-être endommagé et vous devez compacter le fichier MDB. Si un index est corrompu, des problèmes majeurs peuvent en résulter. Vous risquez de perdre des relations existantes (si l'index corrompu est le PK) ou de perdre des données. Donc, vous devez avoir une sauvegarde avant de faire cela. S'il existe un index corrompu, l'opération compacte interactive d'Access vous le dira, mais sinon, vous pouvez rechercher la table MSysCompactErrors qui vous indiquera les erreurs survenues lors du compactage.

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

  1. mauvaise conception de l'application, y compris les versions obsolètes de Jet (Jet 4 avant le service pack 6 était très sensible à cela, et c'est là que je l'ai rencontré).

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

Bien sûr, cette suggestion est très longue, mais c’est certainement une cause de résultats différents (la plus courante consiste à ORDER BY sur l’index corrompu et vous obtiendrez un nombre d’enregistrements différent de celui d’un autre ORDER BY).

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 sélectionner, insérer, mettre à jour, etc. démarrera une transaction que, pour être efficace, vous devez la valider. Appelez connection.autocommit = True ou appelez cursor.execute ("commit") après la requête, puis fetchall.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top