Подтвердить что ты не робот

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

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

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

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

4b9b3361

Ответ 1

Ответ: НЕТ. Я отправляю свой вопрос о домашнем коде 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 SQL Native Client делает это), но эти преобразования скрыты от pyodbc.

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

Ответ 2

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

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"

Ответ 3

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

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

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

Ответ 4

Для 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))

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

Ответ 5

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

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

Ответ 6

Я бы проверил 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 и возвращает результат.

Ответ 7

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

sql='''select a 
       from tbl 
       where b=? 
       and c=? '''

cursor.execute(sql, x, y)
print 'just executed:',(sql, x,y)

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