2014-06-25 1 views
22

के साथ पांडस read_sql पांडस में SQL क्वेरी के साथ पैरामीटर को पारित करने के तरीके के बारे में कोई उदाहरण हैं?पैरामीटर

विशेष रूप से मैं एक PostgreSQL डेटाबेस से कनेक्ट करने के लिए एक SQLAlchemy इंजन का उपयोग कर रहा हूँ। अब तक मैंने पाया कि निम्न काम करता है:

df = psql.read_sql(('select "Timestamp","Value" from "MyTable" ' 
        'where "Timestamp" BETWEEN %s AND %s'), 
        db,params=[datetime(2014,6,24,16,0),datetime(2014,6,24,17,0)], 
        index_col=['Timestamp']) 

पांडा प्रलेखन का कहना है कि पैरामीटर भी एक dict के रूप में पारित किया जा सकता है, लेकिन मैं इस उदाहरण के लिए कोशिश कर काम करने के लिए प्राप्त करने के लिए प्रतीत नहीं कर सकते हैं:

df = psql.read_sql(('select "Timestamp","Value" from "MyTable" ' 
        'where "Timestamp" BETWEEN :dstart AND :dfinish'), 
        db,params={"dstart":datetime(2014,6,24,16,0),"dfinish":datetime(2014,6,24,17,0)}, 
        index_col=['Timestamp']) 

पांडों से इन प्रकार के प्रश्नों को चलाने का अनुशंसित तरीका क्या है?

उत्तर

31

read_sql डॉक्स का कहना है कि इस params तर्क एक सूची, टपल या dict हो सकता है (docs देखें)।

एसक्यूएल क्वेरी में मान प्रदान करने के लिए, अलग-अलग संभावित वाक्यविन्यास देखते हैं: ?, :1, :name, %s, %(name)s (देखें PEP249)।
लेकिन इन सभी संभावनाओं को सभी डेटाबेस ड्राइवरों द्वारा समर्थित नहीं किया गया है, जो वाक्यविन्यास समर्थित है, उस ड्राइवर पर निर्भर करता है जिसका उपयोग आप (psycopg2 अपने मामले में करते हैं) में निर्भर करता है।

अपने दूसरे मामले में, जब एक dict उपयोग कर, आप 'नाम तर्क' का उपयोग कर रहे हैं, और psycopg2 दस्तावेज़ के अनुसार, वे %(name)s शैली का समर्थन (और इसलिए नहीं :name मुझे लगता है), http://initd.org/psycopg/docs/usage.html#query-parameters देखते हैं।
तो का उपयोग कर कि शैली काम करना चाहिए:

df = psql.read_sql(('select "Timestamp","Value" from "MyTable" ' 
        'where "Timestamp" BETWEEN %(dstart)s AND %(dfinish)s'), 
        db,params={"dstart":datetime(2014,6,24,16,0),"dfinish":datetime(2014,6,24,17,0)}, 
        index_col=['Timestamp']) 
+0

के आधार पर भिन्न होता है यह बहुत उपयोगी है - मैं psycopg2 का उपयोग कर रहा हूं, इसलिए '% (name) s वाक्यविन्यास पूरी तरह से काम करता है। – tobycoleman

+0

हमें शायद डॉकस्ट्रिंग में इसके बारे में कुछ उल्लेख करना चाहिए: https: //github.com/pydata/pandas/issues/7573 – joris

+0

यह समाधान अब पोस्टग्रेस पर काम नहीं करता है - किसी को 'नोटेशन' का उपयोग करने की आवश्यकता है, और फिर सुनिश्चित करें एसक्यूएल स्ट्रिंग को 'sqlalchemy.text()' के साथ लपेटने के लिए – hamx0r

1

मैं इस सेटअप का उपयोग SQLite के साथ करता हूं जिसका अर्थ है कि मैं पाइथन में पैरामीटर को संभाल सकता हूं और विशेष रूप से पांडों में नहीं। मेरे लिए अच्छा काम करता है और पढ़ने के लिए आसान है फिर एक क्वेरी और पैरामीटर को read_sql में सीधे फेंकना।

con = sqlite3.connect("mydb.db") 

verses_sql = '''SELECT 
        kjv.b, 
        kjv.id, 
        kjv.t, 
        kjv.v, 
        ke.n, 
        ke.author 
       FROM t_kjv kjv 
       LEFT JOIN key_english ke on kjv.b = ke.b 
       WHERE blah = %s''' % blah 

df_verses = pd.read_sql(verses_sql, con, index_col='id') 

कर रहा इस तरह से मतलब है कि आप भी अगर आप पसंद करते बहु स्ट्रिंग के लिए एक dict पारित कर सकते हैं कि:

>>> d = { 'vars': "variables", 'example': "example" } 
>>> s = "This is an {example} with {vars}" 
>>> s.format(**d) 
'This is an example with variables' 
+0

किसी Sybase और sqlanydb के साथ इस का उपयोग कर रहा है? – toasteez

+7

इसका यह भी अर्थ है कि इस तरह आप केवल मूल्यों की तुलना में एक और अधिक सामान इंजेक्ट कर सकते हैं। वास्तव में यह आपको क्वेरी की प्रकृति को संशोधित करने की अनुमति देता है। यह दृष्टिकोण [एसक्यूएल इंजेक्शन] (https://www.google.com/search?q=sql+injection) के लिए प्रवण है, इसलिए बाइंड चर का उपयोग करने की आवश्यकता है। – YoYo

+0

@toasteez यह पायथन टेम्पलेट स्ट्रिंग प्रतिस्थापन का हिस्सा है, और SQL के साथ कुछ भी नहीं है। तो यह इस्तेमाल डेटाबेस से स्वतंत्र है, और समान रूप से समान रूप से अच्छी तरह से काम करेगा। यद्यपि एसक्यूएल इंजेक्शन आइटम नोट करें। – YoYo