Syllabus
Unit 04 • 6 Class HoursTU Final Exam Core

Database Programming using Python

Tribhuvan University (TU MCA504) पाठ्यक्रम अनुसार यो युनिटले पाइथनबाट रिलेसनल डाटाबेसहरूसँग सम्पर्क गर्ने मानक इन्टरफेस (Python DB-API 2.0 / PEP 249), DDL (संरचना निर्माण) र DML (डाटा फेरबदल) क्वेरीहरू चलाउने, परिणामहरू प्रोसेस गर्ने, तथा वित्तीय सुरक्षाका लागि अनिवार्य मानिने Commit र Rollback ट्रान्ज्याक्सन अपरेसनहरू समेट्छ।

परीक्षा रणनीतिक महत्त्व (Exam Weightage):TU परीक्षामा यो युनिटबाट प्रायः एउटा ५ देखि ८ नम्बरको व्यावहारिक कोडिङ प्रश्न सोधिन्छ (जस्तै: "Write a Python program to connect to a SQLite database, create a table, insert records safely using parameterized queries, and handle commit/rollback in case of exceptions.") साथै "Explain the role of Cursor and differences between fetchone(), fetchmany(), and fetchall()" जस्ता प्रश्नहरू अनिवार्य रूपमा आउँछन्।
Section 01

Python DB-API 2.0 (PEP 249) Architecture

पाइथनमा प्रत्येक डाटाबेस (जस्तै SQLite, MySQL, PostgreSQL, Oracle) को आफ्नै अलग-अलग C-लाइब्रेरी वा प्रोटोकल हुन्छ। यदि प्रत्येक डाटाबेसका लागि पाइथन कोड पूर्ण रूपमा फरक हुन्थ्यो भने एउटा डाटाबेसबाट अर्कोमा सर्न अत्यन्त गाह्रो हुन्थ्यो। यस समस्यालाई समाधान गर्न Python Software Foundation ले PEP 249 (Python Database API Specification v2.0) जारी गर्‍यो।

PEP 249 ले सबै डाटाबेस ड्राइभरहरूका लागि एउटै साझा मापदण्ड तोकिदिएको छ:

  • `connect(...)`: डाटाबेस सर्भर वा स्थानीय फाइलसँग कनेक्सन अब्जेक्ट खोल्ने फङ्सन।
  • Connection Object: यसले डाटाबेस सेसन व्यवस्थापन गर्छ र cursor(), commit(), rollback(), तथा close() विधिहरू प्रदान गर्छ।
  • Cursor Object: यो वास्तविक क्वेरी चलाउने (Execute) र परिणामहरूबाट पङ्क्तिहरू (Rows) तानेर ल्याउने मुख्य माध्यम हो।
FIGURE 4.1: Python DB-API 2.0 (PEP 249) Pipeline ArchitectureTU EXAM SKETCH
+-------------------------------------------------------------------------+
| PYTHON APPLICATION LAYER                                                |
|   import sqlite3 (Built-in) / import mysql.connector (Enterprise)        |
+-------------------------------------------------------------------------+
                                    |
            1. conn = sqlite3.connect("college.db")
                                    v
+-------------------------------------------------------------------------+
| CONNECTION OBJECT (Session Management & Transaction Boundaries)         |
|   Methods: .cursor(), .commit(), .rollback(), .close()                  |
+-------------------------------------------------------------------------+
                                    |
            2. cur = conn.cursor()
                                    v
+-------------------------------------------------------------------------+
| CURSOR OBJECT (Query Execution & Result-Set Traversal)                  |
|   Methods: .execute(), .executemany(), .fetchone(), .fetchall()         |
+-------------------------------------------------------------------------+
                                    |
            3. SQL Query Sent via Socket / Local File I/O
                                    v
+-------------------------------------------------------------------------+
| DATABASE ENGINE (DBMS: SQLite Engine / MySQL Server Daemon)              |
|   Compiles SQL, checks constraints, reads B-Tree tables & returns rows  |
+-------------------------------------------------------------------------+

परीक्षामा स्मरण गर्ने सूत्र: Application ➔ Connect ➔ Connection Object ➔ Cursor Object ➔ Execute Query ➔ Commit/Rollback ➔ Close.

नेपालीमा सार: DB-API 2.0 भनेको एउटा विश्वव्यापी नियम हो। तपाईँ चाहे sqlite3 चलाउनुहोस् वा mysql.connector, कोड लेख्ने तरिका (connect(), cursor(), execute(), commit()) दुरुस्तै एउटै रहन्छ।
Section 02

Establishing Database Connections & SQLite

पाइथनमा सबैभन्दा सहज र लोकप्रिय डाटाबेस SQLite (`sqlite3`) हो, किनभने यसलाई छुट्टै सर्भर इन्स्टल वा कन्फिगर गर्नु पर्दैन। यो सिधै पाइथनको स्ट्यान्डर्ड लाइब्रेरीमा उपलब्ध हुन्छ र डिस्कमा रहेको एउटै फाइलमा सबै टेबुलहरू भण्डारण गर्छ।

१. डिस्क फाइल vs In-Memory Database (`:memory:`)

  • sqlite3.connect("tu_students.db"): कम्प्युटरको हार्डड्राइभमा स्थायी फाइल बनाउँछ। प्रोग्राम बन्द भए पनि डाटा सुरक्षित रहन्छ।
  • sqlite3.connect(":memory:"): कम्प्युटरको RAM मा मात्र अस्थायी डाटाबेस सिर्जना गर्छ। यो युनिट टेस्टिङ र असाध्यै तीव्र गतिको कार्यका लागि प्रयोग गरिन्छ; प्रोग्राम बन्द हुँदा डाटा नष्ट हुन्छ।

२. सुरक्षित कनेक्सन र Exception Handling

import sqlite3

def establish_connection(db_file="tu_exam.db"):
    connection = None
    try:
        # १. डाटाबेससँग कनेक्सन स्थापित गर्ने
        connection = sqlite3.connect(db_file)
        print(f"[सफलता] SQLite डाटाबेस '{db_file}' सँग सम्पर्क जोडियो।")
        print(f"SQLite Version: {sqlite3.sqlite_version}")
        return connection
    except sqlite3.Error as err:
        print(f"[त्रुटि] डाटाबेस जोड्न सकिएन: {err}")
        return None

# कनेक्सन प्रयोग गर्ने र अन्तमा बन्द गर्ने
conn = establish_connection()
if conn:
    # काम सकिएपछि कनेक्सन बन्द गर्नै पर्छ
    conn.close()
    print("डाटाबेस कनेक्सन सुरक्षित रूपमा बन्द गरियो।")
नेपालीमा सार: sqlite3.connect() ले यदि तोकिएको नामको फाइल डिस्कमा भेटेन भने तुरुन्त नयाँ खाली फाइल आफै बनाइदिन्छ। तर MySQL मा भने सर्भर पहिले नै चालु भएको हुनुपर्छ।
Section 03

DDL Queries: CREATE, ALTER & DROP Tables

DDL (Data Definition Language) ले डाटाबेसको ढाँचा वा संरचना (Schema) परिभाषित गर्दछ। यस अन्तर्गत टेबुल सिर्जना गर्ने (CREATE), स्तम्भ थप्ने वा बदल्ने (ALTER), र टेबुल मेटाउने (DROP) पर्दछन्।

TU Exam Golden Rule: DDL स्टेटमेन्टहरू (जस्तै CREATE TABLE) आफै स्वचालित रूपमा कमिट (Auto-committed) हुन्छन्, तर सुरक्षित सफ्टवेयर इन्जिनियरिङ अभ्यास अनुसार सधैं conn.commit() बोलाउनु वा कन्टेक्स्ट म्यानेजर प्रयोग गर्नु राम्रो मानिन्छ।
import sqlite3

conn = sqlite3.connect("mca_college.db")
cursor = conn.cursor()

# १. CREATE TABLE DDL: नयाँ विद्यार्थी तालिका बनाउने
create_table_query = """
CREATE TABLE IF NOT EXISTS students (
    student_id INTEGER PRIMARY KEY AUTOINCREMENT,
    full_name TEXT NOT NULL,
    email TEXT UNIQUE,
    semester INTEGER CHECK(semester >= 1 AND semester <= 4),
    gpa REAL DEFAULT 0.0
);
"""
cursor.execute(create_table_query)
print("[DDL] 'students' तालिका सफलतापूर्वक सिर्जना गरियो।")

# २. ALTER TABLE DDL: नयाँ स्तम्भ (Column) थप्ने
alter_query = """
ALTER TABLE students ADD COLUMN phone_number TEXT;
"""
try:
    cursor.execute(alter_query)
    print("[DDL] 'phone_number' स्तम्भ थपियो।")
except sqlite3.OperationalError:
    print("[DDL] स्तम्भ पहिले नै अवस्थित छ।")

# ३. DROP TABLE DDL (अनावश्यक टेबुल हटाउन):
# cursor.execute("DROP TABLE IF EXISTS temp_records;")

conn.close()
Section 04

DML Queries & SQL Injection Prevention

DML (Data Manipulation Language) ले टेबल भित्रको डाटासँग खेल्छ। यसका मुख्य कमान्डहरू INSERT, UPDATE, र DELETE हुन्।

The Danger of String Formatting: SQL Injection Attack

यदि हामीले Python का f-strings वा string concatenation (+) प्रयोग गरेर प्रयोगकर्ताको इनपुट सिधै SQL मा मिसायौँ भने ह्याकरले सम्पूर्ण डाटाबेस चोर्न वा मेटाउन सक्छ।

FIGURE 4.2: SQL Injection Vulnerability vs Parameterized ProtectionCRITICAL TU CONCEPT
VULNERABLE (F-Strings / String Concatenation):
user_email = "[email protected]' OR '1'='1"
query = f"SELECT * FROM users WHERE email = '{user_email}';"

DATABASE RECEIVES COMPILED STATEMENT:
SELECT * FROM users WHERE email = '[email protected]' OR '1'='1';
====> '1'='1' is ALWAYS TRUE! Authentication bypassed! Entire database dumped!

SAFE (Parameterized Query with Placeholders '?'):
query = "SELECT * FROM users WHERE email = ?;"
cursor.execute(query, (user_email,))

DATABASE DRIVER SEPARATES CODE FROM DATA:
1. SQL query is pre-compiled and immutable.
2. User input is treated STRICTLY as a raw string literal, neutralizing attack vectors!

Parameterized DML Operations (Single & Batch Insertion)

import sqlite3

conn = sqlite3.connect("mca_college.db")
cursor = conn.cursor()

# १. INSERT: एकल रेकर्ड सुरक्षित थप्ने (Tuple of parameters)
insert_query = "INSERT INTO students (full_name, email, semester, gpa) VALUES (?, ?, ?, ?);"
cursor.execute(insert_query, ("Prashant Adhikari", "[email protected]", 3, 3.85))

# २. executemany(): धेरै रेकर्डहरू एकैपटक ब्याच इन्सर्ट गर्ने (High Performance)
batch_students = [
    ("Smriti Rai", "[email protected]", 3, 3.92),
    ("Rabin Thapa", "[email protected]", 2, 3.45),
    ("Manish Giri", "[email protected]", 1, 3.60)
]
cursor.executemany(insert_query, batch_students)

# ३. UPDATE: रेकर्ड परिमार्जन गर्ने
update_query = "UPDATE students SET gpa = ? WHERE email = ?;"
cursor.execute(update_query, (3.90, "[email protected]"))

# ४. DELETE: रेकर्ड हटाउने
delete_query = "DELETE FROM students WHERE semester = ?;"
cursor.execute(delete_query, (1,))

# अनिवार्य: DML पछि डिस्कमा सेभ गर्न commit() कल गर्नै पर्छ!
conn.commit()
print(f"[सफलता] {cursor.rowcount} पङ्क्तिहरू प्रभावित भए र सेभ गरियो।")

conn.close()
नेपालीमा सार: cursor.execute() मा सधैं दोस्रो आर्गुमेन्टको रूपमा टुपल (val1, val2) पठाउनुपर्छ। यसले ह्याकरहरूबाट डाटाबेसलाई पूर्ण सुरक्षित राख्छ। साथै DML चलाएपछि conn.commit() गरेन भने डिस्कमा डाटा सेभ हुँदैन!
Section 05

Processing Query Result Sets: `fetchone`, `fetchmany` & `fetchall`

जब SELECT (DQL) कमान्ड चलाइन्छ, डाटाबेसले नतिजा तुरुन्तै मेमोरीमा खन्याउँदैन। बरु यसले कर्सर (Cursor) लाई पहिलो पङ्क्तिको ठीक अगाडि प्वइन्टरको रूपमा राख्छ। नतिजाहरू झिक्न DB-API ले तीनवटा विधिहरू दिन्छ:

  • `cursor.fetchone()`: नतिजाबाट एउटा मात्र पङ्क्ति (Tuple) फर्काउँछ र कर्सरलाई अर्को पङ्क्तिमा सार्छ। यदि डाटा सकियो भने None फर्काउँछ।
  • `cursor.fetchmany(size)`: तोकिएको संख्या (size) बराबरका पङ्क्तिहरूको लिस्ट [ (...), (...) ] फर्काउँछ (Pagination का लागि उपयुक्त)।
  • `cursor.fetchall()`: बाँकी रहेका सबै पङ्क्तिहरू एकैचोटि लिस्टको रूपमा मेमोरीमा लोड गर्छ।
FIGURE 4.3: Cursor Result Set Navigation & Pointer TraversalMEMORY NAVIGATION
QUERY: cursor.execute("SELECT id, name, gpa FROM students ORDER BY id;")

[CURSOR POINTER]  ----> Before Row 1
-----------------------------------------------------------------------
Row 1: (1, "Prashant", 3.90)  <=== cursor.fetchone() returns Row 1
                                   Pointer advances to Row 2
Row 2: (2, "Smriti", 3.92)    <=== cursor.fetchmany(2) returns [Row 2, Row 3]
Row 3: (3, "Rabin", 3.45)          Pointer advances to Row 4
-----------------------------------------------------------------------
Row 4: (4, "Aayush", 3.75)    <=== cursor.fetchall() returns all remaining:
Row 5: (5, "Deepa", 3.88)          [Row 4, Row 5]
-----------------------------------------------------------------------
[CURSOR POINTER]  ----> At END-OF-DATA (Subsequent fetchone() yields None!)

Performance Tip: लाखौँ रेकर्डहरू भएका ठूला टेबुलमा fetchall() प्रयोग गर्दा RAM भरिन सक्छ। त्यसैले for row in cursor: सिधै चलाउँदा पाइथनले बफर अनुसार जेनेरेटर जस्तै एक-एक पङ्क्ति स्ट्रिम गर्छ।

`sqlite3.Row` को प्रयोग (Accessing Columns by Name)

डिफल्ट रूपमा कर्सरले नतिजालाई इन्डेक्स टुपल (जस्तै row[0], row[1]) को रूपमा दिन्छ। तर conn.row_factory = sqlite3.Row सेट गर्दा हामी डिक्सनरी जस्तै नामबाट (row["full_name"]) डाटा झिक्न सक्छौँ:

import sqlite3

conn = sqlite3.connect("mca_college.db")
# पङ्क्तिहरूलाई नामले पहुँचयोग्य बनाउन row_factory सेट गर्ने:
conn.row_factory = sqlite3.Row
cursor = conn.cursor()

cursor.execute("SELECT student_id, full_name, gpa FROM students WHERE gpa >= ?", (3.5,))

# Memory-Efficient Iteration over Cursor
for row in cursor:
    print(f"ID: {row['student_id']} | नाम: {row['full_name']:<20} | GPA: {row['gpa']}")

conn.close()
Section 06

Transaction Management: ACID, Commit & Rollback

Database Transaction भनेको एक वा धेरै SQL अपरेसनहरूको यस्तो अविभाज्य एकाइ (Single Logical Unit of Work) हो, जहाँ या त सबै अपरेसनहरू पूर्ण रूपमा सफल हुनुपर्छ, अन्यथा एउटा पनि अपरेसनको प्रभाव देखिनु हुँदैन।

ACID Properties (TU Exam Favorite Theory)

A - Atomicity (अविभाज्यता):"All or Nothing". बीचमा कुनै गडबडी भए पूरै ट्रान्ज्याक्सन रद्द हुन्छ।
C - Consistency (एकरूपता):ट्रान्ज्याक्सन अघि र पछि डाटाबेसका सबै नियम (Constraints) कायम रहन्छन्।
I - Isolation (पृथकता):एउटा ट्रान्ज्याक्सनले अर्को समवर्ती ट्रान्ज्याक्सनको अपूर्ण डाटा देख्न पाउँदैन।
D - Durability (स्थायित्व):एकपटक Commit भइसकेपछि प्रणाली बन्द वा क्र्यास भए पनि डाटा हराउँदैन।
FIGURE 4.4: Bank Transfer Transaction Lifecycle & Rollback SafetyACID WORKFLOW
START TRANSACTION (Auto-begun by first DML in Python DB-API)
        |
        v
[STEP 1]: Deduct Rs 5,000 from Ram's Account
        |
        +---- Success? ----> Yes ----> [STEP 2]: Credit Rs 5,000 to Sita's Account
        |                                       |
        |                                       +---- Network Failure / Crash!
        v (If any step fails or error raised)   |
+------------------------------------+          v
| EXCEPTION CAUGHT!                  |   +------------------------------------+
| conn.rollback()                    |   | conn.commit()                      |
| All partial changes reversed!      |   | All steps permanently saved to     |
| Ram loses NO money!                |   | disk database file.                |
+------------------------------------+   +------------------------------------+

परीक्षामुखी Commit र Rollback कोड उदाहरण (Bank Transfer)

import sqlite3

def transfer_funds(sender_id, receiver_id, amount):
    conn = sqlite3.connect("bank.db")
    cursor = conn.cursor()

    try:
        # १. ट्रान्ज्याक्सन सुरु: पठाउनेको खाताबाट रकम घटाउने
        cursor.execute("UPDATE accounts SET balance = balance - ? WHERE acc_id = ?;", (amount, sender_id))
        
        # पठाउनेको मौज्दात ऋणमा गयो कि जाँच गर्ने (Custom Constraint Validation)
        cursor.execute("SELECT balance FROM accounts WHERE acc_id = ?;", (sender_id,))
        sender_balance = cursor.fetchone()[0]
        if sender_balance < 0:
            raise ValueError("रकम अपुग! मौज्दात भन्दा बढी पठाउन मिल्दैन।")

        # २. पाउनेको खातामा रकम थप्ने
        cursor.execute("UPDATE accounts SET balance = balance + ? WHERE acc_id = ?;", (amount, receiver_id))

        # दुवै कार्य सफलतापूर्वक सम्पन्न भएपछि मात्र स्थायी रूपमा सेभ गर्ने:
        conn.commit()
        print(f"[सफलता] रु {amount} खाता {sender_id} बाट {receiver_id} मा ट्रान्सफर भयो।")

    except Exception as error:
        # बीचमा कुनै पनि समस्या आएमा पूरै कारोबार उल्ट्याउने (Undo everything):
        conn.rollback()
        print(f"[विफलता - ROLLBACK] ट्रान्ज्याक्सन रद्द गरियो: {error}")

    finally:
        conn.close()
नेपालीमा सार: बैंकमा पैसा ट्रान्सफर गर्दा यदि रामको खाताबाट घट्यो तर सीताको खातामा जम्मा हुनुअघि सर्भर डाउन भयो भने conn.rollback() ले रामको घटेको पैसा तुरुन्त फिर्ता गरिदिन्छ। दुवै काम सकुशल सकिएपछि मात्र conn.commit() हुन्छ।
Section 07

Full Model CRUD Project: Student Database Management

TU MCA504 परीक्षामा ८ नम्बरको प्रयोगात्मक प्रश्न आउँदा लेख्न मिल्ने पूर्ण, सफा र त्रुटिरहित पाइथन कोड:

import sqlite3

class StudentDatabaseManager:
    def __init__(self, db_name="tu_mca.db"):
        self.db_name = db_name
        self.init_database()

    def get_connection(self):
        conn = sqlite3.connect(self.db_name)
        conn.row_factory = sqlite3.Row
        return conn

    def init_database(self):
        """DDL: तालिका संरचना तयार गर्ने"""
        with self.get_connection() as conn:
            cursor = conn.cursor()
            cursor.execute("""
                CREATE TABLE IF NOT EXISTS student_records (
                    id INTEGER PRIMARY KEY AUTOINCREMENT,
                    roll_no TEXT UNIQUE NOT NULL,
                    name TEXT NOT NULL,
                    subject TEXT NOT NULL,
                    marks REAL CHECK(marks >= 0 AND marks <= 100)
                );
            """)
            conn.commit()

    def add_student(self, roll, name, subject, marks):
        """DML: नयाँ विद्यार्थी थप्ने (Parameterized INSERT)"""
        try:
            with self.get_connection() as conn:
                cursor = conn.cursor()
                cursor.execute(
                    "INSERT INTO student_records (roll_no, name, subject, marks) VALUES (?, ?, ?, ?);",
                    (roll, name, subject, marks)
                )
                conn.commit()
                print(f"[दर्ता] {name} ({roll}) सफलतापूर्वक थपियो।")
        except sqlite3.IntegrityError as e:
            print(f"[त्रुटि] रोल नम्बर {roll} पहिले नै दर्ता छ: {e}")

    def get_all_students(self):
        """DQL: सबै विद्यार्थीहरूको सूची ल्याउने (fetchall)"""
        with self.get_connection() as conn:
            cursor = conn.cursor()
            cursor.execute("SELECT * FROM student_records ORDER BY marks DESC;")
            return cursor.fetchall()

    def update_marks(self, roll, new_marks):
        """DML: प्राप्ताङ्क परिमार्जन गर्ने (UPDATE)"""
        with self.get_connection() as conn:
            cursor = conn.cursor()
            cursor.execute(
                "UPDATE student_records SET marks = ? WHERE roll_no = ?;",
                (new_marks, roll)
            )
            conn.commit()
            print(f"[अपडेट] रोल {roll} को नयाँ प्राप्ताङ्क: {new_marks}")

    def delete_student(self, roll):
        """DML: विद्यार्थी रेकर्ड हटाउने (DELETE)"""
        with self.get_connection() as conn:
            cursor = conn.cursor()
            cursor.execute("DELETE FROM student_records WHERE roll_no = ?;", (roll,))
            conn.commit()
            print(f"[हटाइयो] रोल {roll} को विवरण मेटाइयो।")

# मुख्य परीक्षण कोड (Driver Code):
if __name__ == "__main__":
    db = StudentDatabaseManager()

    # १. इन्सर्ट गर्ने
    db.add_student("MCA-501", "Sushant Karki", "Python Programming", 88.5)
    db.add_student("MCA-502", "Pooja Shrestha", "Python Programming", 92.0)

    # २. प्रदर्शन गर्ने
    print("\n--- विद्यार्थीहरूको प्राप्ताङ्क तालिका ---")
    for s in db.get_all_students():
        print(f"Roll: {s['roll_no']:<10} | Name: {s['name']:<16} | Marks: {s['marks']}")

    # ३. अपडेट र डिलिट
    db.update_marks("MCA-501", 94.0)
    # db.delete_student("MCA-502")
Section 08 • Examination Hall Blueprint

TU Exam Q&A Bank: 10 High-Yield Model Answers

प्रत्येक उत्तरमा द्रुत रिभिजनका लागि 5-Point Quick-Grab Memory Points र परीक्षामा लामो उत्तर लेख्नका लागि Paragraph Elaboration Blueprint समावेश गरिएको छ।

Q1TU Model • PEP 249 & DB-API 2.0 (5 Marks)

What is Python DB-API 2.0 (PEP 249)? Why is a standard database interface necessary in Python?

5-POINT QUICK-GRAB MEMORY ANCHORS:
  • Standard Specification: PEP 249 defines a consistent, uniform API across all relational database access modules.
  • Portability: Application code written for SQLite can switch to MySQL or PostgreSQL by only changing the import and connection string.
  • Core Objects Defined: Mandates two fundamental objects: `Connection` (session/transactions) and `Cursor` (execution/fetching).
  • Standard Exception Hierarchy: Standardizes error handling through base classes like `DatabaseError`, `IntegrityError`, and `OperationalError`.
  • Driver Independence: Prevents vendor lock-in by decoupling SQL engine internals from high-level Python syntax.

Paragraph Blueprint for Exam: सुरुमा PEP 249 को पूर्ण रूप र उद्देश्य लेख्नुहोस्। व्याख्या गर्नुहोस् कि यदि DB-API नभएको भए SQLite का लागि एउटा विधि, MySQL का लागि अर्को, र Oracle का लागि तेस्रो तरिकाले कोड लेख्नुपर्थ्यो।

त्यसपछि Diagram 4.1 जस्तै Connection र Cursor को सम्बन्ध देखाउने रेखाचित्र कोर्नुहोस् र connect(), cursor(), execute(), commit() कसरी सबै ड्राइभरमा समान छन् भनी प्रस्ट्याउनुहोस्।

नेपालीमा सार: DB-API 2.0 भनेको पाइथनको युनिभर्सल चार्जर जस्तै हो। जुनसुकै ब्रान्डको डाटाबेस भए पनि पाइथन कोड एउटै ढाँचामा चल्छ।
Q2TU Model • Connection vs Cursor (5 Marks)

Differentiate between a Connection Object and a Cursor Object in Python Database Programming.

5-POINT QUICK-GRAB MEMORY ANCHORS:
  • Session vs Worker: Connection manages the physical communication pipe and authentication; Cursor is the working pointer that executes SQL.
  • Creation: Connection is instantiated via `driver.connect()`; Cursor is spawned from the connection via `conn.cursor()`.
  • Transaction Scope: `commit()` and `rollback()` belong exclusively to the Connection object.
  • Execution & Fetching: `execute()`, `executemany()`, `fetchone()`, and `fetchall()` belong exclusively to the Cursor object.
  • One-to-Many Relation: A single active Connection can spawn multiple distinct Cursor instances simultaneously.

Paragraph Blueprint for Exam: दुई स्तम्भको तुलना तालिका बनाउनुहोस् (Responsibility, Methods, Creation, Role in ACID)।

प्रस्ट पार्नुहोस् कि कर्सर बिना क्वेरी चल्न सक्दैन, र कनेक्सन बिना कर्सर जन्मन सक्दैन। एउटै कनेक्सनबाट दुईवटा कर्सर (एउटा डाटा पढ्न र अर्को डाटा लेख्न) चलाउन सकिन्छ।

नेपालीमा सार: Connection भनेको डाटाबेस सर्भरसँग जोडिएको टेलिफोन लाइन हो, र Cursor भनेको त्यो लाइनबाट कुरा पठाउने र जवाफ सुन्ने कामदार हो।
Q3TU Model • SQL Injection & Parameterized Queries (8 Marks)

What is SQL Injection? Demonstrate how improper string formatting causes it, and how Parameterized Queries eliminate the vulnerability.

5-POINT QUICK-GRAB MEMORY ANCHORS:
  • Attack Mechanism: Occurs when untrusted user input is directly concatenated into a dynamic SQL statement, altering query syntax.
  • Bypass Payload: Typical payload like `' OR '1'='1` turns `WHERE password = '...'` into an unconditional tautology.
  • Pre-compilation Defense: Parameterized queries pre-compile the SQL template structure prior to inserting user data values.
  • Literal Escaping: Input parameters are treated strictly as scalar data literals, never as executable SQL instructions.
  • Syntax Format: Uses placeholders (`?` in SQLite, `%s` in MySQL) and passes a tuple as the second argument to `cursor.execute()`.

Paragraph Blueprint for Exam: Diagram 4.2 मा देखाइए झैँ सुरुमा असुरक्षित कोड (Vulnerable string concatenation) लेख्नुहोस् र ' OR '1'='1 हाल्दा लगइन कसरी बाइपास हुन्छ देखाउनुहोस्।

त्यसपछि सुरक्षित Parameterized कोड लेख्नुहोस्: cursor.execute("SELECT * FROM users WHERE u=? AND p=?", (u, p))। व्याख्या गर्नुहोस् कि डाटाबेस इन्जिनले पहिले नै क्वेरी कम्पाइल गरिसकेको हुनाले प्रयोगकर्ताको इनपुटलाई केवल सादा अक्षर (Literal string) का रूपमा मात्र हेर्छ, कुनै आदेशका रूपमा होइन।

नेपालीमा सार: स्ट्रिङ जोडेर SQL बनाउँदा प्रयोगकर्ताले आफ्नै SQL कमान्ड घुसाउन सक्छ। तर ? (Placeholders) प्रयोग गर्दा पाइथनले प्रयोगकर्ताको इनपुटलाई केवल डाटा मात्र मानेर सुरक्षित बनाउँछ।
Q4TU Model • Result Traversal Methods (5 Marks)

Compare `fetchone()`, `fetchmany()`, and `fetchall()`. Which method is best for processing large datasets and why?

5-POINT QUICK-GRAB MEMORY ANCHORS:
  • fetchone(): Retrieves exactly one row at a time as a tuple; returns `None` when exhausted; $O(1)$ memory usage.
  • fetchmany(size): Retrieves a list of up to `size` rows; perfectly suited for web pagination and batching.
  • fetchall(): Loads the entire remaining result set into client RAM as a list of tuples; high memory risk on large tables.
  • Cursor as Iterator: `for row in cursor:` streams records using internal chunking without loading the whole table at once.
  • Pointer State: All fetch methods share the same stateful cursor position—calling `fetchone()` followed by `fetchall()` fetches only the remainder.

Paragraph Blueprint for Exam: तीनवटै विधिको रिटर्न टाइप (Single Tuple, List of N Tuples, List of All Tuples) र मेमोरी प्रभाव लेख्नुहोस्।

ठूलो डाटासेट (उदा. १० लाख ग्राहक) का लागि fetchall() ले MemoryError निम्त्याउन सक्छ भनी चेतावनी दिनुहोस्। त्यसैले for row in cursor: वा fetchmany(1000) ब्याच प्रशोधन सबैभन्दा उत्तम अभ्यास हो भनी पुष्टि गर्नुहोस्।

नेपालीमा सार: १ वटा रेकर्ड चाहिए fetchone(), टुक्रा-टुक्रा गरी पेज देखाउन fetchmany(), र सानो टेबल पुरै चाहियो भने fetchall() प्रयोग गरिन्छ।
Q5TU Model • Commit, Rollback & ACID (8 Marks)

Explain the significance of `commit()` and `rollback()` in transaction management. How do they ensure ACID properties?

5-POINT QUICK-GRAB MEMORY ANCHORS:
  • Commit Purpose: Permanently flushes pending uncommitted DML transactions from write-ahead logs/memory to the disk storage file.
  • Rollback Purpose: Aborts the current transaction and reverts the database to its pristine state prior to the transaction's inception.
  • Atomicity Guarantee: Guarantees that intermediate invalid states are never persisted if an unexpected exception occurs.
  • Auto-commit Difference: By default, Python DB-API begins transactions implicitly on the first DML statement and requires explicit commit.
  • try-except-finally Pattern: Critical architectural pattern: `try: ... conn.commit()` and `except: conn.rollback()` ensures bulletproof safety.

Paragraph Blueprint for Exam: ACID का चारवटै अक्षम (Atomicity, Consistency, Isolation, Durability) को छोटो परिभाषा लेख्नुहोस्।

त्यसपछि बैंक फण्ड ट्रान्सफर (Bank Transfer) को उदाहरण दिनुहोस् (Section 6 जस्तै)। देखाउनुहोस् कि यदि रकम काटियो तर जम्मा हुनुअघि क्र्यास भयो भने conn.rollback() नबोलाए बैंकको हिसाब गडबड हुन्छ।

नेपालीमा सार: commit() ले काम पक्का सेभ गर्छ, र rollback() ले कुनै गडबडी भएमा सबै कामलाई पहिलाकै अवस्थामा उल्ट्याइदिन्छ।
Q6TU Model • DDL vs DML Execution (5 Marks)

Differentiate between DDL and DML statements with practical Python code examples for each.

5-POINT QUICK-GRAB MEMORY ANCHORS:
  • Schema vs Data: DDL modifies database structure and table definitions; DML manipulates actual records inside the tables.
  • Commands: DDL includes `CREATE`, `ALTER`, `DROP`, `TRUNCATE`; DML includes `INSERT`, `UPDATE`, `DELETE`.
  • Commit Necessity: DDL statements in many databases auto-commit; DML statements in Python DB-API strictly require `conn.commit()`.
  • rowcount Attribute: After DML execution, `cursor.rowcount` reports how many rows were affected; DDL yields -1.
  • Rollback Capability: DML operations can be undone via `rollback()`; DDL schema modifications generally cannot be rolled back in SQLite.

Paragraph Blueprint for Exam: DDL र DML को भिन्नता तालिका बनाउनुहोस्। त्यसपछि एउटै सफा पाइथन स्क्रिप्टमा CREATE TABLE (DDL) र INSERT INTO (DML) चलाएर देखाउनुहोस्।

विशेष रूपमा उल्लेख गर्नुहोस् कि DML चलाएपछि conn.commit() अनिवार्य हुन्छ र cursor.rowcount ले कतिवटा पङ्क्ति फेरियो भनी बताउँछ।

नेपालीमा सार: DDL ले कोठा (टेबुल) बनाउँछ वा भत्काउँछ। DML ले त्यो कोठा भित्र मान्छे (डाटा) हाल्ने, निकाल्ने वा फेर्ने काम गर्छ।
Q7TU Model • Batch Insertion with executemany() (5 Marks)

Why is `cursor.executemany()` preferred over looping `cursor.execute()` for inserting multiple records?

5-POINT QUICK-GRAB MEMORY ANCHORS:
  • Single Compilation Overhead: `executemany()` compiles and prepares the SQL query execution plan only once, reusing it for all records.
  • I/O & Network Reduction: Sends bulk records to the database engine in an optimized internal pipeline rather than making separate round-trips.
  • Speed Advantage: Often 10x to 50x faster than executing individual `execute()` calls inside a Python `for` loop.
  • Input Structure: Accepts a parameterized query string and a sequence (list/tuple) of parameter sequences.
  • Atomicity Friendly: All batch rows are enclosed in the same transactional context for atomic persistence.

Paragraph Blueprint for Exam: दुई तरिका तुलना गर्नुहोस्: for item in list: cursor.execute(...) vs cursor.executemany(query, list)

पहिलो तरिकामा प्रत्येक पटक Python र SQLite बीच सन्देश आदानप्रदान (Context Switch & Disk Sync) हुन्छ जसले गर्दा प्रोग्राम ढिलो हुन्छ। तर executemany() ले एकल ब्याचमा काम फत्ते गर्छ।

नेपालीमा सार: १० वटा इँटा एक-एक गरी ओसार्नु for loop execute() हो, र सबै इँटा ट्रलीमा एकैचोटि ओसार्नु executemany() हो।
Q8TU Model • Context Manager in Database Programming (5 Marks)

How does the `with` statement (Context Manager) simplify transaction management and resource cleanup in `sqlite3`?

5-POINT QUICK-GRAB MEMORY ANCHORS:
  • Automatic Transaction Management: In `sqlite3`, `with conn:` automatically commits if the block exits cleanly.
  • Automatic Rollback on Exception: If an exception occurs inside the `with` block, `conn.rollback()` is automatically invoked.
  • Boilerplate Reduction: Eliminates the need to write repetitive explicit `try...except...commit()...rollback()` blocks.
  • Resource Leak Prevention: Ensures that file handles and socket connections are systematically cleaned up.
  • Important Caveat: `with conn:` manages the transaction, but does NOT automatically close the connection; `conn.close()` is still needed afterwards.

Paragraph Blueprint for Exam: with sqlite3.connect("demo.db") as conn: को उदाहरण लेख्नुहोस्।

सम्झाउनुहोस् कि यसको पृष्ठभूमिमा __enter__ ले ट्रान्ज्याक्सन सुरु गर्छ र __exit__ ले यदि कुनै अपवाद आएन भने commit() गर्छ, र अपवाद आएमा rollback() गर्छ।

नेपालीमा सार: with conn: लेखेपछि हामीले हातले conn.commit()conn.rollback() लेखिरहनु पर्दैन; पाइथनले आफै सफलतामा सेभ र समस्यामा उल्ट्याइदिन्छ।
Q9TU Model • sqlite3.Row Factory (4 Marks)

What is `sqlite3.Row` and why is it preferred over default tuples for query results?

5-POINT QUICK-GRAB MEMORY ANCHORS:
  • Named Column Access: Allows accessing query fields by column name (`row["email"]`) in addition to numeric index (`row[1]`).
  • Configuration: Enabled by setting `conn.row_factory = sqlite3.Row` immediately after establishing the connection.
  • Code Maintainability: If SQL column order changes, `row["name"]` remains completely valid, whereas `row[1]` would break silently.
  • Case-Insensitive Keys: Column lookups in `sqlite3.Row` are case-insensitive (`row["Name"]` equals `row["name"]`).
  • Dictionary Conversion: Can easily be converted into standard Python dicts via `dict(row)` for JSON API serialization.

Paragraph Blueprint for Exam: डिफल्ट टुपल (उदा. row[2]) मा कुन इन्डेक्समा कुन भ्यालु छ भनी अनुमान गर्न गाह्रो हुन्छ र टेबुलमा नयाँ स्तम्भ थपिँदा इन्डेक्स गडबड हुन्छ।

conn.row_factory = sqlite3.Row राख्दा row['full_name'] लेख्न सकिन्छ जसले सफ्टवेयरलाई परिपक्व र सजिलै बुझिने बनाउँछ।

नेपालीमा सार: नम्बर गनेर row[0], row[1] गर्नु भन्दा सिधै नामबाट row['name'] गरेर डाटा निकाल्न sqlite3.Row प्रयोग गरिन्छ।
Q10TU Model • SQLite vs MySQL Drivers in Python (5 Marks)

Compare `sqlite3` and `mysql.connector` in Python. What architectural differences exist between serverless and server-based databases?

5-POINT QUICK-GRAB MEMORY ANCHORS:
  • Serverless vs Client-Server: SQLite is an embedded library operating on local files; MySQL is a dedicated multi-user daemon listening on port 3306.
  • Installation: `sqlite3` is built directly into Python; `mysql.connector` requires `pip install mysql-connector-python`.
  • Connection Parameters: SQLite needs only a file path; MySQL requires `host`, `user`, `password`, `database`, and `port`.
  • Placeholder Style: SQLite uses `?` (qmark style); MySQL connector uses `%s` (format style).
  • Concurrency: SQLite locks the entire database file during writes; MySQL supports granular row-level locking for massive concurrent users.

Paragraph Blueprint for Exam: दुई स्तम्भको विस्तृत तुलना तालिका बनाउनुहोस् (Architecture, Network Communication, Concurrency, Setup, Placeholder style)।

निष्कर्ष दिनुहोस् कि एकल प्रयोगकर्ता वा डेस्कटप एपका लागि SQLite सर्वश्रेष्ठ छ, तर लाखौँ प्रयोगकर्ता भएको वेब पोर्टल वा बैंकिङ प्रणालीका लागि MySQL वा PostgreSQL अनिवार्य हुन्छ।

नेपालीमा सार: SQLite हाम्रो कम्प्युटरको एउटै फाइलमा बस्छ र कुनै सर्भर चाहिन्न। MySQL भने नेटवर्कमा छुट्टै सर्भरमा बस्छ र धेरै प्रयोगकर्ताले एकैचोटि चलाउन सक्छन्।