A Database is an organized, persistent collection of structured data designed for rapid search, secure multi-user access, and fault-tolerant storage.
While writing data to flat files (like .txt or .csv) works for trivial programs, real-world systems fail with flat files due to:
Relational Database Management Systems (RDBMS): Organize data into tables consisting of Rows (Records/Tuples) and Columns (Attributes/Fields) with relational links governed by Primary Keys and Foreign Keys.
| ACID Pillar | Formal Meaning | Real-World Banking Example |
|---|---|---|
| A — Atomicity | "All or Nothing". All operations in a transaction must succeed; otherwise, the entire transaction is rolled back. | Money is debited from Account A AND credited to Account B. If power fails halfway, money is NOT lost. |
| C — Consistency | Data must conform to all declared schema rules, constraints, and valid states before and after. | Account balance cannot violate a CHECK (balance >= 0) constraint. |
| I — Isolation | Concurrent transactions execute independently without interfering with each other's intermediate state. | Two simultaneous ATM withdrawals don't collide or allow double-spending. |
| D — Durability | Once a transaction is committed, changes are permanently written to non-volatile disk and survive server crashes. | Server power outage after "Transaction Successful" will not erase the deposit. |
SQL is the standard declarative programming language used to interact with relational databases. Instead of writing procedural loops to find records, you declare what you want, and the database query engine optimizes the retrieval path.
| Sublanguage | Full Name | Primary Commands | Purpose |
|---|---|---|---|
| DDL | Data Definition Language | CREATE, ALTER, DROP, TRUNCATE |
Defines or modifies table schemas and structures. |
| DML | Data Manipulation Language | INSERT, UPDATE, DELETE |
Modifies actual data records within tables. |
| DQL | Data Query Language | SELECT, WHERE, ORDER BY |
Retrieves and filters data records from tables. |
| TCL | Transaction Control Language | COMMIT, ROLLBACK, SAVEPOINT |
Manages atomic transaction boundaries. |
Python standardizes all database drivers through PEP 249 (Python Database API Specification v2.0). Whether you connect to SQLite, MySQL, PostgreSQL, or Oracle, the underlying Python API remains identical:
connect(): Opens a communication channel to the database file or remote server.Connection Object: Controls transaction state (commit(), rollback(), close()).Cursor Object: The active database pointer used to execute SQL statements (execute(), executemany()) and fetch result rows.fetchone() (retrieves single row), fetchall() (retrieves all matching rows as a list of tuples), and fetchmany(size).• SQLite: A serverless, embedded database engine. There is no separate server daemon process running. The entire database is stored in a single cross-platform disk file (e.g., academy.db). It is built directly into Python's standard library (import sqlite3). Perfect for mobile apps, desktop tools, and development.
• MySQL: A client-server enterprise RDBMS. The database engine runs as an independent network daemon (typically on port 3306). Python connects across TCP/IP sockets using user authentication (username, password, host). Designed for large-scale web applications with thousands of concurrent users.
data.db file on disk. No network, no server setup!f"SELECT * FROM users WHERE name = '{user_input}'"' OR '1'='1 bypasses authentication!cursor.execute("SELECT * FROM users WHERE name = ?", (user_input,))CRUD stands for the four fundamental persistent operations of any business data system:
CREATE TABLE) and adding records (INSERT INTO).SELECT ... FROM ... WHERE) and fetching rows.UPDATE ... SET ... WHERE).DELETE FROM ... WHERE).INSERT new student into database table.SELECT student record to display profile.UPDATE marks after exam evaluation.DELETE record upon student graduation.import sqlite3
# Step 1: Connect to SQLite (creates file if not present)
conn = sqlite3.connect("devascent_students.db")
cursor = conn.cursor()
# Step 2: CREATE Table
cursor.execute("""
CREATE TABLE IF NOT EXISTS students (
id INTEGER PRIMARY KEY AUTOINCREMENT,
name TEXT NOT NULL,
course TEXT NOT NULL,
gpa REAL NOT NULL
)
""")
conn.commit()
# Step 3: CREATE / INSERT Records using Parameterized Tuples (Secure against Injection)
students_batch = [
("Aman Sharma", "BCA", 8.4),
("Pooja Verma", "B.Tech CS", 9.2),
("Rahul Gupta", "BCA", 7.1)
]
cursor.executemany("INSERT INTO students (name, course, gpa) VALUES (?, ?, ?)", students_batch)
conn.commit()
print(f"[CREATE] Successfully inserted {cursor.rowcount} students.")
# Step 4: READ Records
cursor.execute("SELECT id, name, course, gpa FROM students WHERE gpa >= ?", (8.0,))
high_scorers = cursor.fetchall()
print("\n[READ] High Scorers (GPA >= 8.0):")
for row in high_scorers:
print(f" ID: {row[0]} | Name: {row[1]} | Course: {row[2]} | GPA: {row[3]}")
# Step 5: UPDATE Record
cursor.execute("UPDATE students SET gpa = ? WHERE name = ?", (7.8, "Rahul Gupta"))
conn.commit()
print(f"\n[UPDATE] Updated GPA for Rahul Gupta. Affected rows: {cursor.rowcount}")
# Step 6: DELETE Record
cursor.execute("DELETE FROM students WHERE name = ?", ("Aman Sharma",))
conn.commit()
print(f"[DELETE] Removed Aman Sharma. Affected rows: {cursor.rowcount}")
# Step 7: Clean close
cursor.close()
conn.close()
To connect Python with an external MySQL server, install the official connector driver via:
pip install mysql-connector-python
Key syntax differences from SQLite:
• Connection requires credentials: host, user, password, and database.
• Parameter placeholders use %s instead of ?.
import mysql.connector
from mysql.connector import Error
def connect_mysql_database():
try:
connection = mysql.connector.connect(
host="localhost",
port=3306,
database="academy_db",
user="root",
password="DevAscent@2026"
)
if connection.is_connected():
db_info = connection.get_server_info()
print(f"Connected to MySQL Server Version: {db_info}")
cursor = connection.cursor()
cursor.execute("SELECT DATABASE();")
active_db = cursor.fetchone()
print(f"Active Connected Database: {active_db[0]}")
# Executing parameterized query in MySQL using %s
cursor.execute("SELECT name, email FROM employees WHERE dept_id = %s", (10,))
records = cursor.fetchall()
for emp in records:
print(f" Employee: {emp[0]} <{emp[1]}>")
except Error as err:
print(f"Database Connection Error: {err}")
finally:
if 'connection' in locals() and connection.is_connected():
cursor.close()
connection.close()
print("MySQL connection successfully closed.")
# connect_mysql_database()
This industrial capstone demonstrates ACID transaction reliability: processing a student tuition fee payment with a deduction from their bank balance and an update to their tuition ledger, automatically executing a ROLLBACK if any error occurs.
import sqlite3
def init_billing_database():
conn = sqlite3.connect(":memory:") # In-memory database for ultra-fast sandbox testing
cursor = conn.cursor()
cursor.execute("""
CREATE TABLE student_wallet (
student_id INT PRIMARY KEY,
name TEXT,
balance REAL
)
""")
cursor.execute("""
CREATE TABLE payment_ledger (
payment_id INTEGER PRIMARY KEY AUTOINCREMENT,
student_id INT,
amount REAL,
status TEXT
)
""")
cursor.execute("INSERT INTO student_wallet VALUES (501, 'Kavita Singh', 15000.0)")
conn.commit()
return conn
# Transactional Payment Function
def process_tuition_payment(conn, student_id, amount):
cursor = conn.cursor()
print(f"\nInitiating payment of ₹{amount:,.2f} for Student #{student_id}...")
try:
# Step 1: Check balance
cursor.execute("SELECT balance FROM student_wallet WHERE student_id = ?", (student_id,))
record = cursor.fetchone()
if not record:
raise ValueError("Student ID not found in system!")
current_balance = record[0]
if current_balance < amount:
raise ValueError(f"Insufficient balance! Available: ₹{current_balance:,.2f}")
# Step 2: Deduct from balance
cursor.execute("UPDATE student_wallet SET balance = balance - ? WHERE student_id = ?", (amount, student_id))
# Step 3: Record transaction in ledger
cursor.execute("INSERT INTO payment_ledger (student_id, amount, status) VALUES (?, ?, ?)",
(student_id, amount, "COMPLETED"))
# Step 4: Commit transaction (Atomicity guaranteed)
conn.commit()
print("✅ [TRANSACTION SUCCESS] Tuition payment settled. Receipt generated.")
except Exception as err:
conn.rollback() # Abort all operations; restore original state
print(f"❌ [TRANSACTION FAILED] Reason: {err}")
print(" [ROLLBACK] Reverted all database modifications to protect financial integrity.")
# Test Scenario 1: Successful Payment
db_conn = init_billing_database()
process_tuition_payment(db_conn, 501, 6500.0)
# Test Scenario 2: Overdraft Attempt (Triggers automatic ROLLBACK)
process_tuition_payment(db_conn, 501, 20000.0)
# Verification of final balance
cur = db_conn.cursor()
cur.execute("SELECT name, balance FROM student_wallet WHERE student_id = 501")
final_state = cur.fetchone()
print(f"\nFinal Audited Balance for {final_state[0]}: ₹{final_state[1]:,.2f}")
cursor is a control structure used to traverse and manipulate database records. It executes SQL commands (cursor.execute()) and acts as an iterator or fetch mechanism (fetchone(), fetchall()) to retrieve query results.
conn.commit() is explicitly called to permanently write the changes to the physical disk file or database engine.
? in SQLite or %s in MySQL) prevent this by treating input strictly as literal values rather than executable SQL code.
cursor.fetchone() returns the next single matching record as a tuple, advancing the cursor by one row (or None if no rows remain).cursor.fetchall() returns all remaining matching records at once as a Python list of tuples.
conn.rollback() cancels and reverses all uncommitted database operations performed within the current transaction, restoring the database to its last committed state in case an error occurs.