Theory
એ program જેણે સાઠ હરોળ ગુમાવી
એક senior ની વાત, દર વર્ષે સાચી પડતી: એમની Python ની script એ આખા વર્ગના marks નાખ્યા, દરેક હરોળ બરાબર છાપી, અને સ્વચ્છ રીતે પૂરી થઈ. બીજી સવારે કોષ્ટક ખાલી હતું.
કોઈ ભંગાણ નહીં. કોઈ ભૂલ નહીં. હરોળ છપાઈ હતી, એટલે એ હતી... અને પછી નહોતી.
એક ખૂટતી લીટી બધું સમજાવે છે, અને એ જ લીટી માટે આ પાઠ છે: conn.commit(). પહેલાં ચારેય ક્રિયાઓ પોતે; પછી એમને સાચી બનાવતી સીલ.
Theory
પેન્સિલનું રજિસ્ટર પાછું આવે છે
એકમ 1 નો નિયમ યાદ કરો: databases પહેલાં પેન્સિલથી, COMMIT પર પેનથી લખે છે.
Python નું sqlite3 એને કડક રીતે પાળે છે: તમે execute કરો છો એ દરેક INSERT, UPDATE અને DELETE એ પેન્સિલ છે. તમારો પોતાનો program પેન્સિલનાં નિશાન બરાબર ફરી વાંચે છે (એટલે જ senior નાં prints સંપૂર્ણ લાગ્યાં). પણ શાહી લગાવ્યા વગર રજિસ્ટર બંધ કરો: conn.commit(): અને બહાર નીકળતાં પેન્સિલ ભૂંસાઈ જાય છે. વાચનને શાહી નથી જોઈતી; ફેરફારને હંમેશા જોઈએ છે.
Theory
મૂલ્યો આપવાની સલામત રીત: ? નાં placeholders
ખરેખરાં programs Python નાં variables નાખે છે, ટાઈપ કરેલા સ્થિરાંક નહીં. સલામત સ્વરૂપ ? નાં placeholders વત્તા tuple વાપરે છે:
cur.execute("INSERT INTO marks VALUES (?, ?, ?)", (roll, subject, score))
Module દરેક મૂલ્યને જાતે અવતરણચિહ્નમાં મૂકે છે અને escape કરે છે.
SQL ને + કે f-strings થી ક્યારેય ચોંટાડો નહીં: O'Brien જેવું નામ અવતરણને તોડી નાખે છે, અને દુષ્ટ input તમારી આખી query ફરી લખી શકે છે (SQL injection). એક મૂલ્યને પણ tuple જોઈએ: (roll,) અલ્પવિરામ સાથે.
Practical
પૂરું CRUD, બરાબર સીલ કરેલું
import sqlite3
conn = sqlite3.connect('college.db')
cur = conn.cursor()
# CREATE a row (INSERT)
cur.execute("INSERT INTO marks VALUES (?, ?, ?)", (104, 'DBMS', 67))
# bulk insert: executemany over a list of tuples
new_rows = [(105, 'DBMS', 72), (106, 'DBMS', 58)]
cur.executemany("INSERT INTO marks VALUES (?, ?, ?)", new_rows)
# UPDATE (the recheck, from Python this time)
cur.execute("UPDATE marks SET score = ? WHERE roll = ? AND subject = ?",
(88, 101, 'DBMS'))
print(cur.rowcount) # 1 row affected
# DELETE a withdrawn student's row
cur.execute("DELETE FROM marks WHERE roll = ?", (106,)) # note (106,)
# READ needs no commit: SELECT + fetch as last lesson
cur.execute("SELECT COUNT(*) FROM marks WHERE subject = 'DBMS'")
print(cur.fetchone()[0])
conn.commit() # THE SEAL: changes become permanent NOW
conn.close()
Think first
Senior નો bug શોધો
Senior ની script: connect, cursor, executemany થી 60 INSERT, એમને પાછા SELECT (બધા 60 છપાય છે), conn.close(). ક્યાંય commit નહીં. Tap કરતાં પહેલાં: prints માં 60 હરોળ કેમ દેખાઈ, અને બીજી સવારે કોષ્ટક કેમ ખાલી હતું?
Show the answer
60 INSERT ખુલ્લા transaction ની અંદરનાં પેન્સિલનાં નિશાન હતાં. એ જ connection પોતાની પેન્સિલ વાંચે છે, એટલે SELECT ને બધા 60 દેખાયા અને છપાયા: program અંદરથી સંપૂર્ણ લાગ્યો.
commit વગરના conn.close() એ transaction rollback કરી: પેન્સિલ ભૂંસાઈ, કોષ્ટક જેમનું તેમ. બીજી સવારની તપાસ નવા connection થી થઈ, જે ફક્ત શાહી જુએ છે.
close() પહેલાં એક લીટી: conn.commit(): અને આ કથા ક્યારેય બનતી નથી.
Quiz
Python ના sqlite3 માં commit() વિશે કયું વિધાન **સાચું** છે?
- INSERT/UPDATE/DELETE ને ટકવા conn.commit() જોઈએ; SELECT ને નહીં
- SELECT સહિત દરેક વિધાનને commit() જોઈએ
- Program સફળતાથી પૂરો થાય ત્યારે commit() આપોઆપ થાય છે
- commit() cursor પર બોલાવાય છે: cur.commit()
Show the answer
INSERT/UPDATE/DELETE ને ટકવા conn.commit() જોઈએ; SELECT ને નહીં
વાચન કશું બદલતું નથી, એટલે SELECT ને ક્યારેય commit જોઈતું નથી; દરેક data નો ફેરફાર conn.commit() એને શાહી ન લગાડે ત્યાં સુધી કામચલાઉ છે. વિકલ્પ C એ જૂઠ છે જે data ખાય છે: program નું સામાન્ય રીતે પૂરું થવું આપોઆપ commit કરતું નથી (senior નો bug). અને commit connection પર વસે છે (ફોનની લાઈન transaction ની માલિક છે), cursor પર નહીં: cur.commit() એ AttributeError છે. બે હકીકત, બંને marks લાયક: commit કોને જોઈએ, અને એ કોની માલિકીનું છે.
Watch out
Data કે marks ગુમાવતી ત્રણ ટેવો
String થી બાંધેલું SQL: "...WHERE name = '" + name + "'" એ O'Brien પર તૂટે છે અને SQL injection ખોલે છે: હંમેશા placeholders.
એક ઘટકનું tuple: execute(sql, (roll)) ખુલ્લી સંખ્યા આપે છે અને નિષ્ફળ જાય છે: અલ્પવિરામ સાથે (roll,) લખો.
WHERE વગરનું DELETE: DELETE FROM marks આખું કોષ્ટક ખાલી કરે છે, ચૂપચાપ અને કાયદેસર. પહેલાં WHERE લખો, પછી DELETE, અને પછી cur.rowcount તપાસો.
Theory
એકમ, પૂરો
હાડપિંજર (connect, cursor, execute, close), fetch કરવું (એક, બધું), અને હવે સીલ સાથે લખવું: તમે ResultDesk નું આખું database નું સ્તર બાંધી શકો છો. એકમ 1 નું વચન પણ પળાયું: conn.rollback() એ તમારી Python બાજુની રબર છે, અને તમે SQL માં શીખેલી BEGIN/COMMIT ની અર્થવ્યવસ્થા બરાબર એ જ છે જે sqlite3 આપોઆપ કરે છે. એકમ 4 એ જ college.db ને pandas ને સોંપે છે, જ્યાં આખું કોષ્ટક એક Python નો પદાર્થ બની જાય છે.
Summary
Key takeaways
- બધું CRUD cur.execute() માંથી વહે છે; SELECT fetch સાથે જોડાય છે, ફેરફાર commit સાથે.
- મૂલ્યો ? નાં placeholders અને tuple દ્વારા આપો: SQL ને ક્યારેય string થી ન જોડો (injection, અવતરણના bugs).
- એક મૂલ્ય = અલ્પવિરામ સાથે એક ઘટકનું tuple: (roll,).
- executemany() એક વિધાનને tuples ની list પર જથ્થામાં ચલાવે છે; cur.rowcount અસર પામેલી હરોળ ગણે છે.
- conn.commit() ફેરફારને કાયમી કરે છે; commit વગરનું close() એમને rollback કરે છે: જાણીતો data ગુમાવવાનો bug.
- commit()/rollback() connection નાં છે, cursor નાં નહીં.
- Memory hook: commit શાહી ન લગાડે ત્યાં સુધી પેન્સિલ.