Free Study Material
You already know how to write a SELECT query directly in SQL. Python and MySQL are two separate programs, though — connecting them needs a bridge, so a Python program can send that same kind of query and get results back as ordinary Python data. The mysql.connector module is that bridge.
Two objects work together for every database interaction:
import mysql.connector
mydb = mysql.connector.connect(
host="localhost",
user="root",
password="password",
database="school"
)
mycursor = mydb.cursor()
mycursor.execute("SELECT * FROM STUDENT")
result = mycursor.fetchall()
for row in result:
print(row)
mycursor.execute("SELECT * FROM STUDENT")
first_row = mycursor.fetchone()
print("Just one row:", first_row)
fetchall() returns every matching row as a list of tuples — one tuple per row, exactly matching how you'd already expect a SQL row to look. fetchone() instead returns just a single tuple — the next unread row from the same query — which is why execute() is called a second time above, to give fetchone() a fresh result set to read from.
Note: fetchone() returns just the next single row; fetchall() returns every remaining row at once, as a list. Both are read from the SAME cursor after execute() runs a SELECT.
A Connection links Python to the MySQL server; a Cursor, created from it, executes queries and retrieves results. fetchall() returns every row as a list of tuples — the standard way Python code reads back SQL query results.
Python natively doesn't understand SQL. To make them talk, we need a driver called mysql.connector and a specific 4-step sequence.
Establish the link using mysql.connector.connect().
Create a cursor object. This is the "Worker" that travels to the database to execute queries.
Run the SQL command using cursor.execute("SELECT...").
Retrieve results using fetchall() or fetchone().
When you run a SELECT query, MySQL sends back a table. Python converts this table into a List of Tuples.
| ID | Name |
|---|---|
| 1 | Ravi |
| 2 | Amit |
(A List of Tuples)
fetchall(): Returns ALL rows (List of Tuples).fetchone(): Returns ONE row (Single Tuple) or None.rowcount: Returns the number of rows affected/retrieved.Reading data with SELECT is only half of Python-SQL connectivity — actually changing data (INSERT, UPDATE, DELETE) from Python needs one extra, easy-to-forget step, plus a real security habit worth building from the start.
After executing a data-changing query, you must call mydb.commit() on the Connection object (not the cursor) — without it, MySQL treats the change as temporary and it is never actually saved to the database.
import mysql.connector
mydb = mysql.connector.connect(host="localhost", user="root", password="password", database="school")
mycursor = mydb.cursor()
name = input("Enter name: ")
marks = input("Enter marks: ")
# %s placeholders -- NEVER build the query with f-strings/string concatenation
sql = "INSERT INTO STUDENT (Name, Marks) VALUES (%s, %s)"
mycursor.execute(sql, (name, marks))
mydb.commit()
print("Record inserted successfully.")
Warning: Building a query with an f-string like f"INSERT INTO STUDENT VALUES ('{name}')" is a real SQL Injection risk — a malicious value typed as input could alter the query's meaning entirely. The %s placeholder style, with values passed separately to execute(), is what actually prevents this.
mycursor.execute(sql, values) runs an INSERT/UPDATE/DELETE, but mydb.commit() — called on the Connection, not the Cursor — is what actually saves the change permanently. Using %s placeholders instead of building queries with string formatting is what protects against SQL Injection.
Fetching data (SELECT) is safe—you just look at it.
But when you Insert, Update, or Delete, you are changing the database. Python requires an extra step called Commit to make these changes permanent.
(After cursor.execute)
(Saved in MySQL)
If you forget db.commit() after an INSERT/UPDATE/DELETE, your data will NOT be saved!
Never use string formatting (f-strings) to put user data directly into a query. It is dangerous (SQL Injection).
Instead, use the %s placeholder.
String formatting allows hackers to break your database.
sql = f"INSERT INTO St VALUES ('{name}')"
Let Python handle the quotes safely.
sql = "INSERT INTO St VALUES (%s)"
val = (name, )