2011-03-10 15 views
29

में वास्तविक SQL क्वेरी को कैसे देखें I Python में निम्न कोड का उपयोग करें (एमएस-एक्सेस बेस के लिए pyodbc के साथ)।Python cursor.execute

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

यह ठीक है, लेकिन, रखरखाव प्रयोजनों के लिए, मुझे पता है कि पूर्ण और सटीक एसक्यूएल स्ट्रिंग डेटाबेस के लिए भेज जरूरत है।
क्या यह संभव है और कैसे?

उत्तर

4

उत्तर है: नहीं।

टिप्पणी मुद्दा 163 पर # 1 एल द्वारा ... @ deller.id.au: कर्सर मैं (गूगल समूह और में) परियोजना 'घर Google Code पर मेरे सवाल का जवाब है है पोस्ट। mogrify क्वेरी स्ट्रिंग http://code.google.com/p/pyodbc/issues/detail?id=163

लौट संदर्भ यहाँ के लिए उनकी की pyscopg प्रलेखन के लिए एक लिंक है "mogrify" कर्सर विधि है कि रिपोर्टर की चर्चा करते हुए किया जाता है: http://initd.org/psycopg/docs/cursor.html#cursor.mogrify

pyodbc एक प्रदर्शन नहीं करता एनई एसक्यूएल के अनुवाद: यह पैरामीटर एसक्यूएल सीधे ओडीबीसी ड्राइवर वर्बैटिम से गुजरता है। ओडीबीसी एपीआई द्वारा समर्थित प्रसंस्करण शामिल है पाइथन ऑब्जेक्ट्स से सी प्रकारों का अनुवाद।

एसक्यूएल पर कुछ परिवर्तन ODBC ड्राइवर में प्रदर्शन हो सकता है यह सर्वर से भेजे जाने से पहले (जैसे माइक्रोसॉफ्ट एसक्यूएल मूल क्लाइंट करता है), लेकिन ये परिवर्तनों pyodbc से छिपे हुए हैं।

परिणामस्वरूप मुझे लगता है कि यह pyodbc में एक mogrify फ़ंक्शन प्रदान करने के लिए व्यवहार्य नहीं है।

+1

यह निश्चित रूप से संभव है। इसका मतलब है ओडीबीसी चालक द्वारा किए गए परिवर्तनों को दोबारा लागू करना। आम तौर पर यह कुछ बच निकलेगा। –

-1

एसक्यूएल स्ट्रिंग लिखें और फिर इसे निष्पादित करें:

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

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

अब आप जो कुछ भी आप एसक्यूएल बयान के साथ चाहते हैं कर सकते हैं।

+4

एसक्यूएल इंजेक्शन से बचने के लिए इतना अच्छा नहीं है ... – FerranB

+0

मेरे लिए भी अच्छा नहीं है: मैं अलग-अलग कारणों से एसक्यूएल इंजेक्शन के लिए 'execute' में चर पास करता हूं लेकिन यह भी क्योंकि 'execute' फ़ंक्शन डेटाबेस के अनुसार SQL क्वेरी को संशोधित करता है प्रकार और कॉलम प्रकार के लिए। उदाहरण: मैं क्वेरी में उद्धृत करने के बारे में चिंता किए बिना स्ट्रिंग या पूर्णांक या दिनांक फ़ील्ड पास कर सकता हूं। – philnext

2

आपके द्वारा उपयोग किए जाने वाले ड्राइवर के आधार पर, यह संभव हो सकता है या नहीं भी हो सकता है। कुछ डेटाबेस में, पैरामीटर (? एस) को प्रतिस्थापित कर दिया गया है, क्योंकि उपयोगकर्ता 589983 के उत्तर से पता चलता है (हालांकि चालक को स्ट्रिंग को उद्धृत करने और उन तारों के भीतर उद्धरणों से बचने जैसी कुछ चीजें करना होगा, ताकि निष्पादन योग्य एक बयान में परिणाम हो)।

अन्य ड्राइवर डेटाबेस को संकलित ("तैयार") कथन करने के लिए कहेंगे, और उसके बाद दिए गए मानों का उपयोग करके तैयार कथन निष्पादित करने के लिए कहेंगे। इस तरह से तैयार या पैरामीटरयुक्त बयानों का उपयोग एसक्यूएल इंजेक्शन से बचने में मदद करता है - जब वक्तव्य निष्पादित होता है, डेटाबेस "जानता है" एसक्यूएल का हिस्सा क्या है जिसे आप चलाने के लिए चाहते हैं, और एक मूल्य का हिस्सा क्या है वह बयान

PyODBC documentation की त्वरित स्किमिंग द्वारा निर्णय लेते हुए, ऐसा नहीं लगता है कि वास्तविक SQL निष्पादित हो रहा है, लेकिन मैं गलत हो सकता हूं।

+0

हां, आज मैं दस्तावेज़ में जानकारी नहीं देख सकता। Psycopg2 में – philnext

33

यह ड्राइवर द्वारा अलग है। यहां दो उदाहरण दिए गए हैं:

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" 
+6

कर्सर की 'mogrify()' विधि भी है, जो आपको यह देखने देता है कि किसी दिए गए क्वेरी द्वारा इसे निष्पादित किए बिना (या पहले) निष्पादित किया जाएगा। – kindall

+5

MySQLdb ** '_ last_executed' ** में अपवाद होने पर भी चलाने के लिए अंतिम क्वेरी स्ट्रिंग होती है। संपत्ति ** _ निष्पादित ** त्रुटि अगर कोई नहीं है। [http://stackoverflow.com/a/7190914/653372] – nergeia

+0

ओप विशेष रूप से एमएस एक्सेस के लिए pyodbc कहता है। MySQL या Postgres नहीं – ThatAintWorking

2

डीबग purpuse के लिए मैंने एक चेक फ़ंक्शन बनाया जो बस प्रतिस्थापित करता है? क्वेरी मानों के साथ ... यह उच्च तकनीक नहीं है :) लेकिन यह काम करता है! : डी

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)) 

परिणाम:

चुनें * dbo.MA_ItemsMonthlyBalances से जहां मद = 1 और भंडारण = 2 और FiscalYear = 'asdasd' और BalanceYear = 12,331 और संतुलन = 'आस') और BalanceMonth = 1

यह आप लॉग इन करना या आप जो कुछ भी करना चाहते हैं कर सकते हैं:

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

तुम सिर्फ कुछ अपवाद कार्य करने के लिए पकड़ने जोड़ने की जरूरत है।

1

मैं बाद में 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 को कॉल करता है और इसके परिणाम देता है।

3

अंतिम निष्पादित क्वेरी प्राप्त करने के लिए आप print cursor._last_executed का उपयोग कर सकते हैं।

this में पढ़ें कि आप print cursor.mogrify(query,list) का उपयोग कर पहले या बाद में पूर्ण क्वेरी देखने के लिए भी उपयोग कर सकते हैं।