我在Python中使用以下代碼(使用pyodbc作爲MS-Access基礎)。如何在Python中查看真正的SQL查詢cursor.execute
cursor.execute("select a from tbl where b=? and c=?", (x, y))
沒關係,但出於維護的目的,我需要知道發送到數據庫的完整準確的SQL字符串。
這是可能的和如何?
我在Python中使用以下代碼(使用pyodbc作爲MS-Access基礎)。如何在Python中查看真正的SQL查詢cursor.execute
cursor.execute("select a from tbl where b=? and c=?", (x, y))
沒關係,但出於維護的目的,我需要知道發送到數據庫的完整準確的SQL字符串。
這是可能的和如何?
答案是:NO。 我後我的項目」家谷歌代碼(並在谷歌集團)問題的答案是:由l對問題163
評論#1 ... // @ deller.id.au:光標。 mogrify返回查詢字符串 http://code.google.com/p/pyodbc/issues/detail?id=163
僅供參考這裏是他們的 的 pyscopg文檔的鏈接「mogrify」光標方法,該 記者指的是: http://initd.org/psycopg/docs/cursor.html#cursor.mogrify
pyodbc不執行ny SQL的翻譯:它將參數化的SQL直接傳遞給 ODBC驅動程序逐字地傳遞 。涉及的唯一 處理是將參數從Python對象轉換爲ODBC API支持的C 類型。
在SQL中的一些轉變可能是在ODBC驅動程序執行 之前 被髮送到服務器(例如,Microsoft SQL 本機客戶端做到這一點),但這些 轉變是從 pyodbc隱藏。
因此,我認爲它不是 是可行的,以在pyodbc中提供一個mogrify函數 。
根據您使用的驅動程序,這可能會也可能不會。在一些數據庫中,參數(?
s)被簡單地替換,正如user589983的答案所表明的那樣(儘管驅動程序將不得不做一些事情,比如引用字符串並在這些字符串中轉義引號,以便產生可執行的語句)。
其他驅動程序會要求數據庫編譯(「準備」)該語句,然後要求它使用給定的值執行準備好的語句。通過這種方式,使用準備或參數化語句有助於避免SQL注入 - 在語句執行時,數據庫「知道」您希望運行的SQL的一部分,以及內部使用的值的一部分該聲明。
通過快速瀏覽PyODBC documentation來判斷,似乎沒有獲得執行的實際SQL是可能的,但我可能是錯誤的。
是的,今天我看不到在文檔中的信息。 – philnext
它因司機而異。這裏有兩個例子:
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"
在psycopg2還有光標的'mogrify()'方法,它可以讓你看到什麼命令將被給定的查詢,而無需(或之前)執行它執行。 – kindall
在MySQLdb中**'_ last_executed'**保存最後一個查詢字符串,即使在發生異常時也能運行。如果錯誤,屬性** _執行**爲無。 [http://stackoverflow.com/a/7190914/653372] – nergeia
運算特別說pyodbc的MS Access。不是MySQL或Postgres的 – ThatAintWorking
調試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項= 1和存儲= 2且FiscalYear = 'asdasd' AND BalanceYear = 12331和平衡= 'AAS')AND BalanceMonth = 1
有了這個,你可以登錄或做任何你想要的:
rowcount = self.cur.execute(query,values).rowcount
logger.info(check_sql_string(query,values))
如果你只需要添加一些異常捕獲到的功能。
我回頭檢查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當前只是調用calls._do_query並返回結果。
您可以使用print cursor._last_executed
得到最後執行的查詢。
在this中閱讀您還可以使用print cursor.mogrify(query,list)
在執行之前或之後查看完整查詢。
這當然是可能的。這只是意味着重新實現由ODBC驅動程序執行的轉換。通常這只是一些逃避。 –