Theory
वह program जिसने साठ rows खो दिए
एक senior की story, हर साल सच: उनकी Python script ने एक पूरी class के marks insert किए, हर row सही print किया, और cleanly finish हुई। अगली सुबह table empty थी।
कोई crash नहीं। कोई error नहीं। Rows print हुए थे, तो वे मौजूद थे... और फिर नहीं थे।
एक missing line सब explain करती है, और यह वह line है जिसे burn in करने के लिए यह lesson मौजूद है: conn.commit()। पहले, चार operations ख़ुद; फिर वह seal जो उन्हें असली बनाता है।
Theory
Pencil register वापस
Unit 1 का rule याद कीजिए: databases पहले pencil में लिखते हैं, COMMIT पर pen।
Python का sqlite3 इसे strictly follow करता है: आप जो भी INSERT, UPDATE और DELETE execute करते हैं वह pencil है। आपका अपना program pencil marks fine reread करता है (यही कारण है senior के prints perfect दिखे)। पर register को बिना ink किए close कीजिए: conn.commit(): और pencil बाहर निकलते वक़्त erase हो जाती है। Reads को कोई ink नहीं चाहिए; changes को हमेशा चाहिए।
Theory
Values pass करने का safe तरीक़ा: ? placeholders
असली programs Python variables insert करते हैं, typed constants नहीं। Safe form ? placeholders plus एक tuple इस्तेमाल करता है:
cur.execute("INSERT INTO marks VALUES (?, ?, ?)", (roll, subject, score))
Module हर value को ख़ुद quote और escape करता है।
कभी SQL को + या f-strings से glue मत कीजिए: O'Brien जैसा नाम quoting तोड़ देता है, और एक malicious input आपकी पूरी query rewrite कर सकता है (SQL injection)। एक value को अभी भी एक tuple चाहिए: (roll,) comma के साथ।
Practical
Full CRUD, सही तरीक़े से sealed
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 को diagnose कीजिए
Senior की script: connect, cursor, executemany 60 INSERTs, उन्हें वापस SELECT करना (सभी 60 print होते हैं), conn.close()। कहीं कोई commit नहीं। tap करने से पहले: prints ने 60 rows क्यों दिखाए, और table अगली सुबह empty क्यों थी?
Show the answer
60 INSERTs एक खुले transaction के अंदर pencil marks थे। वही connection अपनी pencil पढ़ता है, तो SELECT ने सभी 60 देखे और print किए: program अंदर से perfect दिखा।
Bina commit conn.close() ने transaction rollback किया: pencil erase, table unchanged। सुबह वाले check ने एक fresh connection इस्तेमाल की, जो सिर्फ़ ink देखता है।
close() से पहले एक line: conn.commit(): और यह story कभी नहीं होती।
Quiz
Python के sqlite3 में commit() के बारे में कौन सा statement TRUE है?
- INSERT/UPDATE/DELETE को persist होने के लिए conn.commit() चाहिए; SELECT को नहीं
- SELECT समेत हर statement को commit() चाहिए
- Program successfully ख़त्म होने पर commit() automatic है
- commit() cursor पर call होता है: cur.commit()
Show the answer
INSERT/UPDATE/DELETE को persist होने के लिए conn.commit() चाहिए; SELECT को नहीं
Reads कुछ नहीं बदलते, तो SELECT को कभी commit नहीं चाहिए; हर data CHANGE conn.commit() के ink करने तक provisional है। Option C वह झूठ है जो data खाता है: normal program exit auto-commit NAHI करता (senior का bug)। और commit connection पर रहता है (phone line transaction रखती है), cursor पर नहीं: cur.commit() एक AttributeError है। दो facts, दोनों marks लायक़: commit किसे चाहिए, और यह किसका है।
Watch out
तीन आदतें जो data या marks खोती हैं
String-built SQL: "...WHERE name = '" + name + "'" O'Brien पर टूटता है और SQL injection खोलता है: हमेशा placeholders।
One-element tuple: execute(sql, (roll)) एक bare number pass करता है और fail होता है: (roll,) comma के साथ लिखिए।
बिना WHERE DELETE: DELETE FROM marks पूरी table चुपचाप और legally खाली कर देता है। पहले WHERE लिखिए, फिर DELETE, और बाद में cur.rowcount check कीजिए।
Theory
Unit, complete
Skeleton (connect, cursor, execute, close), fetching (one, all), और अब seal के साथ writing: आप ResultDesk की पूरी database layer बना सकते हैं। Unit 1 का promise भी रखा गया: conn.rollback() आपका Python-side eraser है, और जो BEGIN/COMMIT semantics आपने SQL में सीखे वही sqlite3 automate करता है। Unit 4 वही college.db pandas को थमाता है, जहाँ एक पूरी table एक Python object बन जाती है।
Summary
Key takeaways
- सभी CRUD cur.execute() से चलता है; SELECT fetch के साथ जोड़ी बनाता है, changes commit के साथ।
- Values ? placeholders और एक tuple के ज़रिए pass कीजिए: SQL कभी string-concatenate मत कीजिए (injection, quote bugs)।
- एक value = comma के साथ एक-element tuple: (roll,)।
- executemany() tuples की एक list पर एक statement bulk-run करता है; cur.rowcount affected rows गिनता है।
- conn.commit() changes permanent बनाता है; बिना commit close() उन्हें rollback कर देता है: classic lost-data bug।
- commit()/rollback() connection के हैं, cursor के नहीं।
- Memory hook: commit के ink करने तक pencil।