MySQL ने प्रश्नों का मानकीकरण किया


80

अपने डेटाबेस में जानकारी डालने के लिए MySQLdb मॉड्यूल का उपयोग करने में मुझे मुश्किल समय आ रहा है। मुझे तालिका में 6 चर सम्मिलित करने की आवश्यकता है।

cursor.execute ("""
    INSERT INTO Songs (SongName, SongArtist, SongAlbum, SongGenre, SongLength, SongLocation)
    VALUES
        (var1, var2, var3, var4, var5, var6)

""")

किसी को यहाँ वाक्य रचना के साथ मेरी मदद कर सकते हैं?

जवाबों:


262

एसक्यूएल प्रश्नों के लिए स्ट्रिंग इंटरपोलेशन का उपयोग करने से सावधान रहें, क्योंकि यह इनपुट मापदंडों से सही ढंग से बच नहीं पाएगा और आपके एप्लिकेशन को एसक्यूएल इंजेक्शन कमजोरियों के लिए खुला छोड़ देगा। अंतर मामूली लग सकता है, लेकिन वास्तव में यह बहुत बड़ा है

गलत (सुरक्षा मुद्दों के साथ)

c.execute("SELECT * FROM foo WHERE bar = %s AND baz = %s" % (param1, param2))

सही (भागने के साथ)

c.execute("SELECT * FROM foo WHERE bar = %s AND baz = %s", (param1, param2))

यह इस भ्रम में जोड़ता है कि SQL कथन में मापदंडों को बांधने के लिए उपयोग किए जाने वाले संशोधक अलग-अलग DB API कार्यान्वयनों के बीच भिन्न होते हैं और यह कि mysql क्लाइंट लाइब्रेरी printfअधिक आमतौर पर स्वीकृत 'के बजाय स्टाइल सिंटैक्स का उपयोग करती है?' मार्कर (उदाहरण के लिए प्रयुक्त python-sqlite)।


3
@Specto IMO यह हमेशा सही और सुरक्षित कार्यान्वयन के तरीकों के साथ रहने के लिए समझ में आता है। यह सही आदतें और प्रोग्रामिंग की एक अच्छी संस्कृति बनाता है। यह भी कोई नहीं जानता है कि भविष्य में आप किस तरह से कोड का उपयोग करेंगे; कोई व्यक्ति इसे बाद में अन्य सिस्टम या वेबसाइट के लिए उपयोग कर सकता है।
रोमन पोडलिनोव

@BryanHunt आप का उपयोग चालू कर सकते हैं? कहीं एक तर्क के साथ, लेकिन यह हतोत्साहित किया जाता है क्योंकि यह आपको ज्यादा नहीं बताता कि कौन सा तर्क कहां जाता है। (उसी को% s के बारे में कहा जा सकता है, जो निश्चित रूप से उसी कारण से हतोत्साहित किया जाता है।) अधिक जानकारी यहाँ: python.org/dev/peps/pep-0249/#paramstyle
kqr

1
Php / pdo से आने वाला मैं printfस्टाइल- %sमार्कर होने पर मेगा-उलझन में था, और मुझे इस बात का डर था कि मैं कमजोर प्रश्न लिख रहा था। समाशोधन के लिए धन्यवाद कि चिंता! :)
दारोगा ठीक

18
जब यह एक एकल पैरामीटर है तो अल्पविराम रखना याद रखें: c.execute("SELECT * FROM foo WHERE bar = %s", (param1,))
मैरीस लियान

1
कर्सर निष्पादित करने के मापदंडों पर संदर्भ के लिए (और% s अभी भी क्यों आवश्यक है), MySQLdb
RedBarron

50

आपके पास कुछ विकल्प उपलब्ध हैं। आप अजगर के स्ट्रिंग पुनरावृत्ति के साथ आराम करना चाहते हैं। यह एक ऐसा शब्द है जिसे आप भविष्य में खोज करने में अधिक सफलता प्राप्त कर सकते हैं जब आप इस तरह से सामान जानना चाहते हैं।

प्रश्नों के लिए बेहतर:

some_dictionary_with_the_data = {
    'name': 'awesome song',
    'artist': 'some band',
    etc...
}
cursor.execute ("""
            INSERT INTO Songs (SongName, SongArtist, SongAlbum, SongGenre, SongLength, SongLocation)
            VALUES
                (%(name)s, %(artist)s, %(album)s, %(genre)s, %(length)s, %(location)s)

        """, some_dictionary_with_the_data)

आपके विचार में संभवतः आपके सभी डेटा किसी ऑब्जेक्ट या शब्दकोश में पहले से ही हैं, दूसरा प्रारूप आपके लिए बेहतर होगा। जब आपको वापस आना है और एक साल में इस विधि को अपडेट करना है तो यह एक स्ट्रिंग में "% s" दिखावे को गिनने के लिए बेकार है :)


2
ऐसा लगता है कि SQL स्टेटमेंट में एक से अधिक जगहों पर डिक्शनरी वेरिएशन बेहतर तरीके से काम करता है। स्थितिगत दृष्टिकोण के साथ, हमें चर को कई बार पास करने की आवश्यकता है क्योंकि यह संदर्भित है, जो बहुत वांछनीय नहीं है।
कोडवर्ड

15

लिंक किए गए डॉक्स निम्नलिखित उदाहरण देते हैं:

   cursor.execute ("""
         UPDATE animal SET name = %s
         WHERE name = %s
       """, ("snake", "turtle"))
   print "Number of rows updated: %d" % cursor.rowcount

तो आपको बस इसे अपने कोड में अनुकूलित करने की आवश्यकता है - उदाहरण:

cursor.execute ("""
            INSERT INTO Songs (SongName, SongArtist, SongAlbum, SongGenre, SongLength, SongLocation)
            VALUES
                (%s, %s, %s, %s, %s, %s)

        """, (var1, var2, var3, var4, var5, var6))

(यदि SongLength संख्यात्मक है, तो आपको% s के बजाय% d का उपयोग करने की आवश्यकता हो सकती है)।


1
क्या यह काम करेगा जहाँ var1 और var2 में "या 'जैसे चैटर होते हैं।
sheki

3
AFAIK आपको %sकोई फर्क नहीं पड़ता कि किस प्रकार का उपयोग करना है। @ शेखी: हां
थिएपस्टर

7

वास्तव में, भले ही आपका चर (SongLength) संख्यात्मक हो, फिर भी आपको पैरामीटर को सही ढंग से बांधने के लिए इसे% s के साथ प्रारूपित करना होगा। यदि आप% d का उपयोग करने का प्रयास करते हैं, तो आपको एक त्रुटि मिलेगी। यहाँ इस लिंक से एक छोटा सा अंश है http://mysql-python.sourceforge.net/MySQLdb.html :

क्वेरी करने के लिए, आपको पहले एक कर्सर की आवश्यकता होती है, और फिर आप उस पर प्रश्नों को निष्पादित कर सकते हैं:

c=db.cursor()
max_price=5
c.execute("""SELECT spam, eggs, sausage FROM breakfast
          WHERE price < %s""", (max_price,))

इस उदाहरण में, max_price = 5 क्यों, फिर, स्ट्रिंग में% s का उपयोग करें? क्योंकि MySQLdb इसे SQL शाब्दिक मान में बदल देगा, जो स्ट्रिंग '5' है। जब यह समाप्त हो जाएगा, तो क्वेरी वास्तव में कहेगी, "... कीमत <5"।


हाँ, यह एक अजीब ठीक है ... आपको लगता है कि "प्रिंटफ़" प्रारूप का मतलब होगा ... वास्तव में प्रिंटफ़ प्रारूप और न केवल हर जगह% s का उपयोग करना।
fthinker

6

चुने हुए उत्तर के विकल्प के रूप में, और मार्सेल के उसी सुरक्षित शब्दार्थ के साथ, यहां मूल्यों को निर्दिष्ट करने के लिए पायथन शब्दकोश का उपयोग करने का एक कॉम्पैक्ट तरीका है। आपके द्वारा कॉलम जोड़ने या हटाने के लिए संशोधित करने में आसान होने का लाभ है:

  meta_cols=('SongName','SongArtist','SongAlbum','SongGenre')
  insert='insert into Songs ({0}) values ({1})'.
        .format(','.join(meta_cols), ','.join( ['%s']*len(meta_cols) ))
  args = [ meta[i] for i in meta_cols ]
  cursor=db.cursor()
  cursor.execute(insert,args)
  db.commit()

जहां मेटा डालने के लिए मान रखने वाला शब्दकोश है। अपडेट उसी तरह से किया जा सकता है:

  meta_cols=('SongName','SongArtist','SongAlbum','SongGenre')
  update='update Songs set {0} where id=%s'.
        .format(','.join([ '{0}=%s'.format(c) for c in meta_cols ]))
  args = [ meta[i] for i in meta_cols ]
  args.append( songid )
  cursor=db.cursor()
  cursor.execute(update,args)
  db.commit()

7
मैं प्रभावित हूँ ... आप अजगर कोड को अपठनीय बनाने में कामयाब रहे!
इरोहब अल असिमी

1

पहला उपाय अच्छी तरह से काम करता है। मैं यहां एक छोटा विवरण जोड़ना चाहता हूं। सुनिश्चित करें कि आप जिस वेरिएबल को बदलने / अपडेट करने की कोशिश कर रहे हैं, वह एक प्रकार का स्ट्रगल होना चाहिए। मेरा mysql प्रकार दशमलव है, लेकिन मुझे क्वेरी को निष्पादित करने में सक्षम होने के लिए पैरामीटर चर बनाना होगा।

temp = "100"
myCursor.execute("UPDATE testDB.UPS SET netAmount = %s WHERE auditSysNum = '42452'",(temp,))
myCursor.execute(var)

0

यहाँ यह करने का एक और तरीका है। यह MySQL की आधिकारिक वेबसाइट पर प्रलेखित है। https://dev.mysql.com/doc/connector-python/en/connector-python-api-mysqlcursor-execute.html

भावना में, यह @ ट्रे स्टाउट के उत्तर के उसी मैकेनिक का उपयोग कर रहा है। हालाँकि, मुझे यह एक अच्छा और अधिक पठनीय लगता है।

insert_stmt = (
  "INSERT INTO employees (emp_no, first_name, last_name, hire_date) "
  "VALUES (%s, %s, %s, %s)"
)
data = (2, 'Jane', 'Doe', datetime.date(2012, 3, 23))
cursor.execute(insert_stmt, data)

और चर की किसी भी आवश्यकता को बेहतर ढंग से समझाने के लिए:

NB: नोट किया जा रहा भागने।

employee_id = 2
first_name = "Jane"
last_name = "Doe"

insert_stmt = (
  "INSERT INTO employees (emp_no, first_name, last_name, hire_date) "
  "VALUES (%s, %s, %s, %s)"
)
data = (employee_id, conn.escape_string(first_name), conn.escape_string(last_name), datetime.date(2012, 3, 23))
cursor.execute(insert_stmt, data)
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.