๐Ÿ“˜ CodingMarble Learn

Connecting Python to MySQL: Send SQL, Get Rows Back

Python can talk to a MySQL database using the mysql.connector module. connect() opens a connection with host, user, password and database. cursor() makes a cursor, the object that carries SQL to the database and brings results back. execute() runs one SQL statement. For INSERT, UPDATE and DELETE you must call commit() on the connection to save changes. For SELECT, fetchone() gives the next row as a tuple, fetchall() gives all remaining rows as a list of tuples, and rowcount tells how many rows were fetched or changed. Values are put into queries with %s placeholders (passing a tuple to execute) or with format().

๐ŸŽฌ Step-by-step story

  1. import mysql.connector, then connect() builds a bridge from Python to the MySQL server using host, user, password and database.
  2. cursor() puts a small cart on the bridge. The cursor carries your SQL to the database and brings rows back.
  3. execute('SELECT โ€ฆ') sends the query. The rows wait in the cursor. fetchone() takes one row; fetchall() takes all the rest; rowcount counts rows fetched so far.
  4. execute('INSERT โ€ฆ') changes the table only for now. commit() saves it for good. Without commit, the change is lost when you close.
  5. Put values into a query safely with %s: execute('โ€ฆ WHERE Marks > %s', (80,)). Or build the string with format(). Close the cursor and connection at the end.
  6. Your turn: press fetchone and fetchall. Watch rows leave the cursor and rowcount change.

Tip: drag the 3D scene to turn it. Use two fingers to zoom.

๐Ÿค” Common doubts, cleared

Do I need MySQL installed to use mysql.connector?

Yes, a MySQL server must be running (on your computer or another), and the connector module must be installed with pip.

What exactly is a cursor?

An object that carries SQL to the database and holds the rows that come back, so you can fetch them one by one or all together.

Why did fetchall() give an empty list?

Earlier fetch calls already took all the rows. Each row can be fetched only once per execute.

My INSERT ran but the row is not in the table. Why?

You did not call con.commit(). Without it the change is thrown away.

Why write (80,) with a comma?

execute needs a tuple of values. (80) is just the number 80; (80,) is a one-item tuple.

Why connect Python to a database?

Python is good at logic and user screens; MySQL is good at storing and searching lots of data safely. Together, a Python program (the front end) can store and read data in MySQL (the back end).

Install the connector once: pip install mysql-connector-python. Then:

import mysql.connector as sql

Step by step: connect, cursor, execute

import mysql.connector as sql
con = sql.connect(host='localhost', user='root',
                  passwd='your_password', database='school')
if con.is_connected():
    print('Connected')
cur = con.cursor()
cur.execute('SELECT * FROM student')

Reading results: fetchone, fetchall, fetchmany, rowcount

After a SELECT, the rows wait in the cursor's result set. Each row comes as a tuple.

cur.execute('SELECT RollNo, Name FROM student')
r = cur.fetchone()      # (1, 'Asha')
print(cur.rowcount)     # 1
rest = cur.fetchall()   # [(2,'Ravi'), (3,'Zoya')]
print(cur.rowcount)     # 3
for row in rest:
    print(row[0], row[1])

Changing data: INSERT, UPDATE, DELETE and commit()

cur.execute("INSERT INTO student VALUES (4, 'Om', 'Pune', 70)")
con.commit()
print(cur.rowcount, 'row inserted')

cur.execute('UPDATE student SET Marks = Marks + 2 WHERE Marks < 60')
con.commit()
print(cur.rowcount, 'rows updated')

commit() belongs to the connection (con.commit()), not the cursor. It makes the changes permanent. Without it, changes are thrown away when the program ends. (con.rollback() undoes changes not yet committed.) Finally: cur.close() and con.close().

Putting values into queries: %s and format()

Using %s placeholders (preferred)

roll = int(input('Roll: '))
cur.execute('SELECT * FROM student WHERE RollNo = %s', (roll,))
print(cur.fetchone())

cur.execute('INSERT INTO student VALUES (%s, %s, %s, %s)', (5, 'Kabir', 'Jaipur', 66))
con.commit()

Values go in a tuple as the second argument. A single value still needs a comma: (roll,). The connector adds quotes where needed and protects against harmful input (SQL injection). Always write %s, even for numbers.

Using format() or f-strings

q = "SELECT * FROM student WHERE Marks > {} AND City = '{}'".format(80, 'Delhi')
cur.execute(q)

Here the string is built first, so you must add quotes around text values yourself. It is fine for practice, but %s is safer for real input.

Try it: a mini menu program

Write a menu: 1 Add student, 2 Show all, 3 Search by roll, 4 Exit. Use execute with %s for add and search, commit() after add, fetchall() for show and fetchone() for search. Test: add a student and forget commit(); restart and see it is missing. Then add commit() and try again. Use the 3D free-play step to predict what fetchone and fetchall return.

Key formulas and definitions

Worked examples

1. Write code to connect to database 'library' on localhost as user 'root' with password 'abc' and print whether it is connected.

import mysql.connector as sql con = sql.connect(host='localhost', user='root', passwd='abc', database='library') print(con.is_connected()) # True

2. Table student has 5 rows. After cur.execute('SELECT * FROM student'), the code calls fetchone() twice and then fetchall(). How many rows does fetchall() return, and what is cur.rowcount at the end?

fetchone() twice takes rows 1 and 2. fetchall() returns the remaining 3 rows. rowcount = 5 (all rows fetched so far).

3. Display all students with Marks above 80 using %s.

cur.execute('SELECT Name, Marks FROM student WHERE Marks > %s', (80,)) for name, marks in cur.fetchall(): print(name, marks)

4. Insert a student whose details are typed by the user, then save.

r = int(input('Roll: ')); n = input('Name: '); c = input('City: '); m = int(input('Marks: ')) cur.execute('INSERT INTO student VALUES (%s, %s, %s, %s)', (r, n, c, m)) con.commit() print(cur.rowcount, 'record added')

5. Write the same search using format(): show students from a city typed by the user.

city = input('City: ') q = "SELECT * FROM student WHERE City = '{}'".format(city) cur.execute(q) print(cur.fetchall()) # note the quotes around {} for text

6. A program runs cur.execute('DELETE FROM student WHERE Marks < 40') and then closes, but the rows are still in the table. Why? Fix it.

The change was never committed. Add con.commit() after execute, then close: con.commit(); cur.close(); con.close().

Common mistakes

Practice quiz

1. Which method creates a cursor?
2. fetchone() returns ____ when no rows are left.
3. Which is needed to save an INSERT permanently?
4. fetchall() returns:
5. Which is the correct placeholder style for mysql.connector?

Practice: answer these yourself

Type or choose your answer, then press Check. Use a hint if you are stuck; the full solution appears after you answer.

Frequently asked questions

What is the difference between fetchone() and fetchall()?

fetchone() returns the next single row as a tuple (or None). fetchall() returns all remaining rows as a list of tuples.

Why is commit() needed in Python MySQL?

commit() makes INSERT, UPDATE and DELETE changes permanent. Without it, the changes are lost when the connection closes.

What is rowcount in Python MySQL?

A cursor property that gives the number of rows fetched so far for SELECT, or the number of rows affected for INSERT, UPDATE and DELETE.

Where this is taught

CBSE (India)Class 12Database Management

Learn first

Related lessons

All Computer Science lessons