Как увидеть реальный SQL-запрос в Python cursor.execute

Я использую следующий код в Python (с pyodbc для базы MS-Access).

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

Это нормально, но для целей технического обслуживания мне нужно знать полную и точную строку SQL, отправляемую в базу данных.
Это возможно и как?

7 Solutions collect form web for “Как увидеть реальный SQL-запрос в Python cursor.execute”

Он отличается драйвером. Вот два примера:

 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" 

Ответ – нет. Я размещаю свой вопрос о домашнем коде Google проекта (и в группе Google), так это ответ:

Комментарий № 1 по вопросу 163 по l … @ deller.id.au: cursor.mogrify строка запроса запроса http://code.google.com/p/pyodbc/issues/detail?id=163

Для справки здесь приведена ссылка на документацию pyscopg на их метод «mogrify» курсора, который репортер ссылается на: http://initd.org/psycopg/docs/cursor.html#cursor.mogrify

pyodbc не выполняет никаких таких переводов SQL: он передает параметризованный SQL прямо в драйвер ODBC дословно. Единственной обработкой является перевод параметров из объектов Python в типы C, поддерживаемые API ODBC.

Некоторое преобразование на SQL может выполняться в драйвере ODBC до его отправки на сервер (например, Microsoft Native Client делает это), но эти преобразования скрыты от pyodbc.

Следовательно, я думаю, что невозможно реализовать функцию mogrify в pyobbc.

В зависимости от используемого драйвера это может быть или не быть возможным. В некоторых базах данных параметры ( ? S) просто заменяются, как предполагает ответ пользователя589983 (хотя драйверу придется делать некоторые вещи, такие как цитирование строк и экранирование кавычек в этих строках, чтобы привести к выполнению исполняемого файла).

Другие драйверы попросят базу данных скомпилировать («подготовить») инструкцию и затем попросить ее выполнить подготовленный оператор с использованием заданных значений. Таким образом, использование подготовленных или параметризованных операторов помогает избежать SQL-инъекций – во время выполнения оператора база данных «знает», что является частью SQL, который вы хотите запустить, и что является частью значения, используемого в это заявление.

Судя по быстрому сокращению документации PyODBC , похоже, что получение фактического SQL-исполнения возможно, но я могу ошибаться.

Для debug purpuse я создал функцию проверки, которая просто заменяет? с значениями запроса … это не высокая технология :), но он работает! : 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)) 

Результат:

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

С помощью этого вы можете войти в систему или сделать все, что хотите:

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

Если вам нужно просто добавить какое-то исключение в функцию.

Вы можете использовать print cursor._last_executed для получения последнего выполненного запроса.

Прочитайте в этом ответе, что вы также можете использовать print cursor.mogrify(query,list) чтобы просмотреть полный запрос до или после выполнения.

Я бы проверил cursor._last_executed впоследствии, но если вы хотите, чтобы они были распечатаны в реальном времени, не меняя каждый кадр, попробуйте этот патч обезьяны:

 def log_queries(cur): def _query(q): print q # could also use logging return cur._do_query(q) cur._query = _query conn = MySQLdb.connect( read_default_file='~/.my.cnf' ) cur = conn.cursor() log_queries(cur) cur.execute('SELECT %s, %s, %s', ('hello','there','world')) 

Это очень зависит от MySQLdb (и может быть разбит на более поздние версии). Он работает, потому что cur._query в настоящее время просто вызывает вызовы ._do_query и возвращает его результат.

Напишите строку sql, а затем выполните ее:

 sql='''select a from tbl where b=? and c=? ''' cursor.execute(sql, x, y) print 'just executed:',(sql, x,y) 

Теперь вы можете делать все, что хотите, с помощью инструкции SQL.

  • Не все параметры были использованы в инструкции SQL (Python, MySQL)
  • Использование команд% s в операторах выполнения (python) в mySQL и postgreSQL?
  • Как умножить и суммировать два столбца с группой в django
  • Набор запросов Django-фильтра на «кортежи» значений для нескольких столбцов
  • SQLAlchemy: ограничение в той же строке, что и где
  • Является ли запрос SQLAlchemy уязвимым для инъекционных атак?
  • SQLAlchemy - order_by по отношениям для таблицы соединений
  • SQLAlchemy: предотвращение автоматического закрытия
  • django select_related в шаблоне
  • Почему SQLite быстрее, чем Redis, в этом простом бенчмарке?
  • PostgreSQL - как запустить VACUUM из кода вне транзакционного блока?
  • Python - лучший язык программирования в мире.