80 votes

Comment voir la vraie requête SQL dans Python cursor.execute en utilisant pyodbc et MS-Access

J'utilise le code suivant en Python (avec pyodbc pour une base MS-Access).

cursor.execute("select a from tbl where b=? and c=?", (x, y))

C'est correct mais, à des fins de maintenance, j'ai besoin de connaître la chaîne SQL complète et exacte envoyée à la base de données.
Est-ce possible et comment ?

79voto

samplebias Points 19805

Il diffère selon le conducteur. Voici deux exemples :

import MySQLdb
mc = MySQLdb.connect()
r = mc.cursor()
r.execute('select %s, %s', ("foo", 2))
r._executed
"select 'foo', 2"

import psycopg2
pc = psycopg2.connect()
r = pc.cursor()
r.execute('select %s, %s', ('foo', 2))
r.query
"select E'foo', 2"

15voto

joseph Points 199

Vous pouvez utiliser print cursor._last_executed pour obtenir la dernière requête exécutée.

Lire en este répondre que vous pouvez également utiliser print cursor.mogrify(query,list) pour voir la requête complète avant ou après son exécution.

12voto

philnext Points 1308

La réponse est : NON. J'ai posté ma question sur le Google Code maison du projet (et dans le Google Group) et la réponse est :

Commentaire n°1 sur le problème 163 par l...@deller.id.au : cursor.mogrify return query string http://code.google.com/p/pyodbc/issues/detail?id=163

Pour référence, voici un lien vers le documentation pyscopg de leur de leur méthode de curseur "mogrify" à laquelle le le journaliste fait référence : http://initd.org/psycopg/docs/cursor.html#cursor.mogrify

pyodbc n'effectue pas de telles traductions du SQL : il transmet SQL paramétré directement au le pilote ODBC mot pour mot. Le seul traitement traitement impliqué est la traduction des paramètres des objets Python aux types C supportés par l'API ODBC.

Certaines transformations sur le SQL peuvent être dans le pilote ODBC avant qu'il ne soit avant d'être envoyé au serveur (par exemple, Microsoft SQL Native Client le fait) mais ces transformations transformations sont cachées à pyodbc.

Par conséquent, je pense qu'il n'est pas faisable de fournir une fonction mogrify dans pyodbc.

4voto

piertoni Points 675

Pour le débogage, j'ai créé une fonction de vérification qui remplace simplement ? par les valeurs de la requête... ce n'est pas de la haute technologie :) mais ça marche ! :D

def check_sql_string(sql, values):
    unique = "%PARAMETER%"
    sql = sql.replace("?", unique)
    for v in values: sql = sql.replace(unique, repr(v), 1)
    return sql

query="""SELECT * FROM dbo.MA_ItemsMonthlyBalances
                   WHERE Item = ? AND Storage = ? AND FiscalYear = ? AND BalanceYear = ? AND Balance = ? AND BalanceMonth = ?"""
values = (1,2,"asdasd",12331, "aas)",1)

print(check_sql_string(query,values))

Le résultat :

SELECT * FROM dbo.MA_ItemsMonthlyBalances WHERE Item = 1 AND Storage = 2 AND FiscalYear = 'asdasd' AND BalanceYear = 12331 AND Balance = 'aas') AND BalanceMonth = 1

Avec cela, vous pouvez vous connecter ou faire ce que vous voulez :

rowcount = self.cur.execute(query,values).rowcount
logger.info(check_sql_string(query,values))

Si vous en avez besoin, il suffit d'ajouter des exceptions à la fonction.

3voto

dcrosta Points 11219

Selon le pilote que vous utilisez, cela peut être possible ou non. Dans certaines bases de données, les paramètres ( ? s) sont simplement remplacés, comme le suggère la réponse de l'utilisateur 589983 (bien que le pilote doive faire certaines choses, comme citer des chaînes et échapper les guillemets dans ces chaînes, afin d'obtenir une déclaration exécutable).

D'autres pilotes demanderont à la base de données de compiler ("préparer") l'instruction, puis lui demanderont d'exécuter l'instruction préparée en utilisant les valeurs données. C'est ainsi que l'utilisation d'instructions préparées ou paramétrées permet d'éviter les injections SQL : au moment où l'instruction est exécutée, la base de données "sait" ce qui fait partie de l'instruction SQL que vous souhaitez exécuter et ce qui fait partie d'une valeur utilisée dans cette instruction.

A en juger par un rapide survol de la Documentation PyODBC Dans le cas de l'exécution du code SQL, il ne semble pas possible d'obtenir l'exécution du code SQL, mais je peux me tromper.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X