2008-10-23 6 views
49

पायथन 2.5 के साथ SQLite3 का उपयोग करके, मैं एक सूची के माध्यम से पुन: प्रयास करने की कोशिश कर रहा हूं और आइटम के नाम के आधार पर डेटाबेस से किसी आइटम का वजन खींच रहा हूं।SQLite पैरामीटर प्रतिस्थापन समस्या

मैंने "?" का उपयोग करने की कोशिश की पैरामीटर प्रतिस्थापन एसक्यूएल इंजेक्शन को रोकने के लिए सुझाव दिया लेकिन यह काम नहीं करता है। उदाहरण के लिए, जब मैं का उपयोग करें:

for item in self.inventory_names: 
    self.cursor.execute("SELECT weight FROM Equipment WHERE name = ?", item) 
    self.cursor.close() 

मैं त्रुटि मिलती है:

sqlite3.ProgrammingError: Incorrect number of bindings supplied. The current statement uses 1, and there are 8 supplied.

मेरा मानना ​​है कि यह किसी भी तरह डेटाबेस की प्रारंभिक निर्माण के कारण होता है; मॉड्यूल मैंने बनाया है जो वास्तव में डीबी बनाता है 8 बाइंडिंग करता है।

cursor.execute("""CREATE TABLE Equipment 
    (id INTEGER PRIMARY KEY, 
    name TEXT, 
    price INTEGER, 
    weight REAL, 
    info TEXT, 
    ammo_cap INTEGER, 
    availability_west TEXT, 
    availability_east TEXT)""") 

हालांकि, जब मैं प्रत्येक आइटम नाम के लिए कम-सुरक्षित "% s" प्रतिस्थापन का उपयोग, यह सिर्फ ठीक काम करता है। इस तरह:

for item in self.inventory_names: 
    self.cursor.execute("SELECT weight FROM Equipment WHERE name = '%s'" % item) 
    self.cursor.close() 

मुझे यह नहीं पता कि मुझे लगता है कि मेरे पास 8 बाइंडिन क्यों हैं जब मैं केवल एक कॉल कर रहा हूं। मेरे द्वारा यह कैसे किया जा सकता है?

+0

कॉलम की संख्या बाइंडिंग की संख्या नहीं है। क्वेरी में "?" की संख्या बाइंडिंग की संख्या है। –

+0

हाँ, मुझे पता है। मुझे लगा कि कोड किसी भी तरह से "निर्माण तालिका" कथन द्वारा संदर्भित बाइंडिंग का उपयोग करने का प्रयास कर रहा था। मुझे एहसास नहीं हुआ कि यह आइटम में अक्षरों की संख्या को संदर्भित करता है। – crystalattice

उत्तर

118

Cursor.execute() विधि अनुक्रम को दूसरे पैरामीटर के रूप में अपेक्षा करता है। आप एक स्ट्रिंग की आपूर्ति कर रहे हैं जो 8 वर्ण लंबा होता है।

self.cursor.execute("SELECT weight FROM Equipment WHERE name = ?", [item]) 

अजगर पुस्तकालय संदर्भ 13.13.3: sqlite3 Cursor Objects

बजाय निम्नलिखित फार्म का उपयोग करें।

2

क्या आपने यह कोशिश की है? :

for item in self.inventory_names: 
    t = (item,) 
    self.cursor.execute("SELECT weight FROM Equipment WHERE name = ?", t) 
    self.cursor.close() 

cursor.execute() दूसरे पैरामीटर के रूप में अनुक्रम (सूची, tuple) की अपेक्षा करता है। (-> ddaa)

35

मैं आधा दिन बिताया है यह पता लगाने की क्यों कुछ इस तरह मुझे एक त्रुटि देना होगा की कोशिश कर रहा:

cursor.execute("SELECT * from ? WHERE name = ?", (table_name, name)) 

केवल कि तालिका नाम पता लगाने के लिए parametrized नहीं किया जा सकता। उम्मीद है कि यह कुछ लोगों को कुछ समय बचाने में मदद करेगा।

+1

आप कुछ ऐसा कर सकते हैं: 'cursor.execute (" SELECT * से% s कहां नाम =? "% Table_name, (name,)) ', हालांकि यह आपके प्रोग्राम को SQL इंजेक्शन हमलों के लिए कमजोर बना सकता है। – plok

+6

उन परिस्थितियों के लिए जहां उपयोगकर्ता इनपुट तालिका निर्धारित करता है, मैं तालिका के नाम को एक तीर से बाहर खींचता हूं और इनपुट की सामग्री अप्रत्याशित होने पर अपवाद उठाता हूं। शायद इसके बारे में जाने के लिए _best_ तरीका नहीं है, लेकिन एसक्यूएल इंजेक्शन में परिणामस्वरूप कम उत्तरदायी लगता है। – James

+0

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

1

उद्धरण (क्या माता-पिता का मतलब है?)? माता-पिता मेरे लिए काम करते हैं। मैंने कोशिश की (शाब्दिक) '?' लेकिन मैं

ProgrammingError: Incorrect number of bindings supplied. The current statement uses 0, and there are 1 supplied.

हो रही है जब मैंने किया था:

SELECT fact FROM factoids WHERE key LIKE (?)

के बजाय:

SELECT fact FROM factoids WHERE key LIKE '?'

यह काम किया।

क्या यह कुछ अजगर 2.6 चीज है?

+1

यदि आप sqlite3 के पैरामीटर प्रतिस्थापन का उपयोग कर रहे हैं (पाइथन के% s स्ट्रिंग इंटरपोलेशन के बजाय), फिर? उद्धृत नहीं किया जाना चाहिए, यानी 'तथ्य कहां से तथ्य चुनें जहां कुंजी पसंद है?'। यह बस होता है एसक्यूएल में ब्रैकेट्स अर्थ को नहीं बदलता है, इसलिए तथ्यों को चुनें तथ्य कहां से (?) 'के बराबर है()। –

+0

यदि आप Django का उपयोग कर रहे हैं और आपकी क्वेरी 'तथ्यों से चुनें तथ्य "कहां"% s "की तरह है तो आप उद्धरण चिह्नों से भी बचना चाहेंगे। 'cursor.execute()' उस क्वेरी में बाध्यकारी के रूप में% s को पहचान नहीं पाएगा। तो 'cursor.execute का उपयोग करें (" तथ्यों से तथ्यों का चयन करें जहां कुंजी% s की तरह है ", (key_name,)) ' – MrOodles

-5

execute("select fact from factoids where key like ?", "%%s%" % val) 

प्रयास करें आप ? के आसपास कुछ भी लपेट नहीं है सब पर, अजगर SQLite सही ढंग से एक उद्धृत इकाई में परिवर्तित होगा।

21

cursor.execute का तर्क जो डेटाबेस में डाले गए मानों का प्रतिनिधित्व करता है, एक टुपल (अनुक्रम) होना चाहिए। हालांकि इस उदाहरण पर विचार करें और देखें कि क्या हो रहा है:

>>> ('jason') 
'jason' 

>>> ('jason',) 
('jason',) 

पहला उदाहरण इसके बजाय एक स्ट्रिंग का मूल्यांकन करता है; इसलिए एकल मूल्यवान टुपल का प्रतिनिधित्व करने का सही तरीका दूसरे मूल्यांकन में है। किसी भी तरह, आपकी त्रुटि को ठीक करने के लिए नीचे दिया गया कोड।

self.cursor.execute("SELECT weight FROM Equipment WHERE name = ?", (item,)) 

इसके अलावा, तारों के रूप में cursor.execute मूल्य तर्क दे रही है (जो तुम क्या कर रहे) उदाहरण में पहली मूल्यांकन में परिणाम और त्रुटि मिल रहा है में यह परिणाम है।

+2

मुझे लगता है कि यह स्वीकार्य उत्तर होना चाहिए – Kirk

0

वस्तुओं का प्रत्येक तत्व एक ट्यूपल होना चाहिए। (आइटम,) का उपयोग करके

for item in self.inventory_names: 
self.cursor.execute("SELECT weight FROM Equipment WHERE name = ?", (item,)) 

आप इसे एक टपल के बजाय एक स्ट्रिंग बना रहे हैं:

names = ['Joe', 'Bob', 'Mary'] 

आप निम्न करना चाहिए: संभालने नाम कुछ इस तरह लग रहा है।