Nearby lessons

152 of 159

Python - Database Select Records

📌 What You Will Learn
  • Retrieve data from a database table using the SQL SELECT statement
  • Fetch one row at a time using fetchone() with a while loop
  • Fetch all remaining rows at once using fetchall() and a for loop
  • Fetch a specified number of rows using fetchmany() and the size argument
  • Compare the fetchone(), fetchmany(), and fetchall() methods

Introduction — Retrieving Records from the Database

Retrieving records from a database table is one of the most important operations in Python Database Programming. In these applications, we will learn how to retrieve employee information from the employees table using three different Cursor methods.

  • App9 - using fetchone() to retrieve employee records one by one.
  • App10 - using fetchall() to retrieve all employee records at once.
  • App11 - using fetchmany() to retrieve a specified number of employee records at a time.

Each application first executes a SELECT query using cursor.execute() and then uses a fetch method to retrieve the resulting records.

employees Table
      │
      ▼
SELECT * FROM employees
      │
      ▼
cursor.execute()
      │
      ▼
    Result Set
      │
      ├── fetchone()   → One Row at a Time
      ├── fetchmany()  → Specified Number of Rows
      └── fetchall()   → All Rows at Once
        

The SQL SELECT Statement

The SQL SELECT statement is used to retrieve data from a Database table.

General Syntax

SELECT column1, column2, ...
FROM table_name;
        

To retrieve all columns:

SELECT *
FROM table_name;
        

In our applications, we use:

SELECT * FROM employees;
        

It retrieves all columns and all available rows from the employees table.

Here:

SQL Part Meaning
SELECT Retrieve data
* Select all columns
FROM Specifies the table
employees Table from which records are retrieved

App9 — Select All Employees Using fetchone()

In this application, we will learn how to retrieve employee information from the employees table using the fetchone() method.

The program first executes a SELECT query and then repeatedly calls fetchone() to retrieve employee records one by one.

This application demonstrates:

  • Using the SQL SELECT statement
  • Using cursor.execute()
  • Using fetchone()
  • Fetching one row at a time
  • Using while row is not None
  • Processing the complete result set
  • Handling Oracle Database errors
  • Closing the Cursor and Connection

The program performs the following operations:

Import cx_Oracle
      │
      ▼
Create Connection
      │
      ▼
Create Cursor
      │
      ▼
Execute SELECT Query
      │
      ▼
fetchone()
      │
      ▼
Row Available?
   /         Yes        No
  │          │
  ▼          ▼
Print Row   Stop
  │
  ▼
fetchone()
  │
  └────────────► Repeat
        
🐍Code Cell
1import cx_Oracle
2 
3try:
4 con = cx_Oracle.connect('scott/tiger@localhost')
5 cursor = con.cursor()
6 
7 cursor.execute("select * from employees")
8 
9 row = cursor.fetchone()
10 
11 while row is not None:
12 print(row)
13 row = cursor.fetchone()
14 
15except cx_Oracle.DatabaseError as e:
16 if con:
17 con.rollback()
18 
19 print("There is a problem with sql :", e)
20 
21finally:
22 if cursor:
23 cursor.close()
24 
25 if con:
26 con.close()
Output
No output captured.

What is fetchone()?

The fetchone() method is used to fetch only one row from the result set.

Each time fetchone() is called, it returns the next available row.

row = cursor.fetchone()
        

If another row is available:

fetchone()
    │
    ▼
Next Row
        

If no more rows are available:

fetchone()
    │
    ▼
None
        

Therefore, None indicates that the complete result set has been processed.

Suppose the result set contains four employee records:

Employee 1
Employee 2
Employee 3
Employee 4
        

Repeated calls to fetchone() behave like this:

Call Returned Value
1st fetchone() Employee 1
2nd fetchone() Employee 2
3rd fetchone() Employee 3
4th fetchone() Employee 4
5th fetchone() None

fetchone() — Processing Rows with a while Loop

The first row is retrieved using:

row = cursor.fetchone()
        

The fetchone() method retrieves one row from the result set and stores it in the variable row.

For example:

row = (100, 'Sachin', 1000, 'Mumbai')
        

A Database row is normally represented as a tuple.

The values in the row tuple can be understood as:

Index Column Example
row[0] Employee Number 100
row[1] Employee Name Sachin
row[2] Employee Salary 1000
row[3] Employee Address Mumbai

The program uses a while loop to process every fetched row:

while row is not None:
    print(row)
    row = cursor.fetchone()
        

The loop continues as long as row contains an employee record. When row becomes None, the condition becomes false and the loop terminates.

We do not know how many employee records may be available in the Database, so the program keeps fetching rows until fetchone() returns None. This makes the program work whether the table contains:

1 employee
10 employees
100 employees
1000 employees
        

The loop ends automatically after the last available row.

How fetchone() Works

SELECT Query
     │
     ▼
fetchone()
     │
     ▼
First Row
     │
     ▼
Print Row
     │
     ▼
fetchone()
     │
     ▼
Second Row
     │
     ▼
Print Row
     │
     ▼
   ...
     │
     ▼
fetchone()
     │
     ▼
None
     │
     ▼
Loop Ends
        

App9 — Worked Example and Sample Output

Suppose the employees table contains:

+-----+--------+------+--------+
| eno | ename  | esal | eaddr  |
+-----+--------+------+--------+
| 100 | Sachin | 1000 | Mumbai |
| 200 | Dhoni  | 2000 | Ranchi |
| 300 | Kohli  | 3000 | Delhi  |
+-----+--------+------+--------+
        

The query:

SELECT * FROM employees;
        

creates a result set containing these three rows.

fetchone() Call 1

The first call to fetchone() returns (100, 'Sachin', 1000, 'Mumbai'). The condition row is not None is true, so print(row) prints that record.

fetchone() Call 2

At the end of the first loop iteration, fetchone() returns the second record (200, 'Dhoni', 2000, 'Ranchi'). The loop condition is still true, so the second employee is printed.

fetchone() Call 3

The next call returns (300, 'Kohli', 3000, 'Delhi') and the third employee record is printed.

fetchone() Call 4 — No More Records

After processing the third employee, no more rows are available. row becomes None, so row is not None becomes False and the while loop terminates.

Sample Output

(100, 'Sachin', 1000, 'Mumbai')
(200, 'Dhoni', 2000, 'Ranchi')
(300, 'Kohli', 3000, 'Delhi')
        

Each employee record is displayed one at a time.

What Happens if the Table is Empty?

If the employees table contains no records, the SELECT query returns an empty result set. The first call to fetchone() returns None, so the while condition is false immediately and the loop body does not execute.

SELECT
  │
  ▼
No Rows
  │
  ▼
fetchone()
  │
  ▼
None
  │
  ▼
Loop Does Not Execute
        

App9 — Complete Program with Comments

The same program with comments for each step:

🐍Code Cell
1# Import Oracle Database module
2import cx_Oracle
3 
4try:
5 # Establish connection with Oracle Database
6 con = cx_Oracle.connect('scott/tiger@localhost')
7 
8 # Create Cursor object
9 cursor = con.cursor()
10 
11 # Execute SELECT query
12 cursor.execute("select * from employees")
13 
14 # Fetch the first employee record
15 row = cursor.fetchone()
16 
17 # Continue until fetchone() returns None
18 while row is not None:
19 
20 # Display current employee record
21 print(row)
22 
23 # Fetch the next employee record
24 row = cursor.fetchone()
25 
26except cx_Oracle.DatabaseError as e:
27 
28 # Rollback if required
29 if con:
30 con.rollback()
31 
32 # Display Database error
33 print("There is a problem with sql :", e)
34 
35finally:
36 
37 # Close Cursor
38 if cursor:
39 cursor.close()
40 
41 # Close Connection
42 if con:
43 con.close()
Output
No output captured.

App9 — Exception Handling, commit() and Resource Cleanup

This application only retrieves data using SELECT. It does not insert, update, or delete employee records.

Therefore, the program does not call:

con.commit()
        

Compare:

Operation Changes Data? commit() Normally Required?
INSERT Yes Yes
UPDATE Yes Yes
DELETE Yes Yes
SELECT No No

The program handles Oracle Database errors using:

except cx_Oracle.DatabaseError as e:
        

If a Database error occurs, execution moves to the except block. The exception information is stored in e.

The exception block contains a rollback:

if con:
    con.rollback()
        

If a Database error occurs, temporary uncommitted changes associated with the transaction can be rolled back.

The error is displayed using:

print("There is a problem with sql :", e)
        

The actual Oracle Database error information is available in the exception object e.

The finally block executes whether the program succeeds or an exception occurs. Its purpose is to release the Database resources.

finally:
    if cursor:
        cursor.close()

    if con:
        con.close()
        
       try
        │
   ┌────┴────┐
   │         │
Success    Exception
   │         │
   │       except
   │         │
   └────┬────┘
        ▼
     finally
        │
        ▼
Close Resources
        

The Cursor is closed using cursor.close(), which releases the Cursor resource after all employee records have been processed.

The Database connection is closed using con.close(), which releases the connection with Oracle Database.

App10 — Select All Employees Using fetchall()

In the previous application, we used fetchone() to retrieve employee records one by one.

In this application, we will learn how to retrieve all employee records at once from the employees table using the fetchall() method.

The program first executes a SELECT query and then calls fetchall() to retrieve all remaining rows from the result set.

What is fetchall()?

The fetchall() method is used to retrieve all remaining rows from the result set.

rows = cursor.fetchall()
        

After executing a SELECT query, fetchall() collects all available rows and returns them together.

SELECT Query
     │
     ▼
Result Set
     │
     ├── Row 1
     ├── Row 2
     ├── Row 3
     └── Row 4
          │
          ▼
      fetchall()
          │
          ▼
[Row 1, Row 2, Row 3, Row 4]
        

Each individual row is normally represented as a tuple.

Complete Program

The complete program performs the following operations:

Import cx_Oracle
      │
      ▼
Connect to Oracle Database
      │
      ▼
Create Cursor
      │
      ▼
Execute SELECT Query
      │
      ▼
fetchall()
      │
      ▼
Store All Rows in data
      │
      ▼
for row in data
      │
      ▼
Print Each Row
      │
      ▼
Close Resources
        
🐍Code Cell
1import cx_Oracle
2 
3try:
4 con = cx_Oracle.connect('scott/tiger@localhost')
5 cursor = con.cursor()
6 
7 cursor.execute("select * from employees")
8 
9 data = cursor.fetchall()
10 
11 for row in data:
12 print(row)
13 
14except cx_Oracle.DatabaseError as e:
15 if con:
16 con.rollback()
17 
18 print("There is a problem with sql :", e)
19 
20finally:
21 if cursor:
22 cursor.close()
23 
24 if con:
25 con.close()
Output
No output captured.

fetchall() — Iterating with a for Loop

After executing the SELECT query, the program calls:

data = cursor.fetchall()
        

fetchall() retrieves all remaining rows from the query result and stores the returned collection in data.

For example:

data = [
    (100, 'Sachin', 1000, 'Mumbai'),
    (200, 'Dhoni', 2000, 'Ranchi'),
    (300, 'Kohli', 3000, 'Delhi')
]
        
  • The outer collection contains all employee records.
  • Each inner tuple represents one employee record.
  • Each value inside a tuple represents one column value.

The program uses a for loop to process every record:

for row in data:
    print(row)
        

During every iteration, one employee tuple from data is assigned to row. The loop automatically stops after processing the final employee record.

Suppose the employees table contains:

+-----+--------+------+--------+
| eno | ename  | esal | eaddr  |
+-----+--------+------+--------+
| 100 | Sachin | 1000 | Mumbai |
| 200 | Dhoni  | 2000 | Ranchi |
| 300 | Kohli  | 3000 | Delhi  |
| 400 | Rohit  | 4000 | Mumbai |
+-----+--------+------+--------+
        

After data = cursor.fetchall(), the conceptual value of data is:

[
    (100, 'Sachin', 1000, 'Mumbai'),
    (200, 'Dhoni', 2000, 'Ranchi'),
    (300, 'Kohli', 3000, 'Delhi'),
    (400, 'Rohit', 4000, 'Mumbai')
]
        

The for loop executes four iterations, printing each employee record. The output will be similar to:

(100, 'Sachin', 1000, 'Mumbai')
(200, 'Dhoni', 2000, 'Ranchi')
(300, 'Kohli', 3000, 'Delhi')
(400, 'Rohit', 4000, 'Mumbai')
        

Individual column values can be accessed using indexes:

Expression Meaning Example Value
row[0] Employee Number 100
row[1] Employee Name Sachin
row[2] Employee Salary 1000
row[3] Employee Address Mumbai

What Happens if the Table is Empty?

If the employees table does not contain any records, fetchall() returns an empty collection:

[]
        

The for loop does not execute even once.

App10 — Displaying Individual Column Values

Instead of printing the complete tuple with print(row), we can access and display the individual column values of each employee:

🐍Code Cell
1import cx_Oracle
2 
3try:
4 con = cx_Oracle.connect('scott/tiger@localhost')
5 cursor = con.cursor()
6 
7 cursor.execute("select * from employees")
8 
9 data = cursor.fetchall()
10 
11 for row in data:
12 print("Employee Number :", row[0])
13 print("Employee Name :", row[1])
14 print("Employee Salary :", row[2])
15 print("Employee Address:", row[3])
16 print()
17 
18except cx_Oracle.DatabaseError as e:
19 print("There is a problem with sql :", e)
20 
21finally:
22 if cursor:
23 cursor.close()
24 
25 if con:
26 con.close()
Output
Employee Number : 100
Employee Name   : Sachin
Employee Salary : 1000
Employee Address: Mumbai

App10 — Complete Program with Comments

The complete App10 program with comments for each step:

🐍Code Cell
1# Import Oracle Database module
2import cx_Oracle
3 
4try:
5 # Establish connection with Oracle Database
6 con = cx_Oracle.connect('scott/tiger@localhost')
7 
8 # Create Cursor object
9 cursor = con.cursor()
10 
11 # Execute SELECT query
12 cursor.execute("select * from employees")
13 
14 # Fetch all employee records
15 data = cursor.fetchall()
16 
17 # Process every employee record
18 for row in data:
19 
20 # Display current employee record
21 print(row)
22 
23except cx_Oracle.DatabaseError as e:
24 
25 # Rollback if required
26 if con:
27 con.rollback()
28 
29 # Display Database error
30 print("There is a problem with sql :", e)
31 
32finally:
33 
34 # Close Cursor
35 if cursor:
36 cursor.close()
37 
38 # Close Database connection
39 if con:
40 con.close()
Output
No output captured.

App11 — Select Records Using fetchmany()

In the previous applications, we learned how to retrieve Database records using fetchone() and fetchall().

In this application, we will learn how to retrieve a specified number of employee records at a time using the fetchmany() method.

The fetchmany() method is useful when we do not want to retrieve all records at once.

What is fetchmany()?

The fetchmany() method is used to retrieve a specified number of rows from the result set.

cursor.fetchmany(size)
        

Here, size represents the maximum number of rows that should be fetched.

Example:

data = cursor.fetchmany(3)
        

This asks the Cursor to fetch up to 3 rows from the current position of the result set.

Statement Maximum Rows Requested
fetchmany(1) 1
fetchmany(2) 2
fetchmany(5) 5
fetchmany(10) 10

Why do we use fetchmany()?

fetchmany() provides a middle approach between fetchone() and fetchall().

fetchone()
    │
    ▼
One Row

fetchmany(n)
    │
    ▼
Specified Number of Rows

fetchall()
    │
    ▼
All Remaining Rows
        

If a query returns many records, we may not want to load all of them at once. With fetchmany(), records can be processed in smaller batches.

Complete Program

The program performs the following operations:

Import cx_Oracle
      │
      ▼
Connect to Oracle Database
      │
      ▼
Create Cursor
      │
      ▼
Execute SELECT Query
      │
      ▼
fetchmany(3)
      │
      ▼
Fetch Up to 3 Records
      │
      ▼
Store Records in data
      │
      ▼
for row in data
      │
      ▼
Print Each Row
      │
      ▼
Close Resources
        
🐍Code Cell
1import cx_Oracle
2 
3try:
4 con = cx_Oracle.connect('scott/tiger@localhost')
5 cursor = con.cursor()
6 
7 cursor.execute("select * from employees")
8 
9 data = cursor.fetchmany(3)
10 
11 for row in data:
12 print(row)
13 
14except cx_Oracle.DatabaseError as e:
15 if con:
16 con.rollback()
17 
18 print("There is a problem with sql :", e)
19 
20finally:
21 if cursor:
22 cursor.close()
23 
24 if con:
25 con.close()
Output
No output captured.

fetchmany() — Cursor Position and Multiple Calls

Suppose the query result contains six employee records:

Row 1
Row 2
Row 3
Row 4
Row 5
Row 6
        

When we execute:

data = cursor.fetchmany(3)
        

the first three rows are returned:

Row 1
Row 2
Row 3
        

The Cursor position moves forward.

Before fetchmany(3)

Cursor
  │
  ▼
Row 1
Row 2
Row 3
Row 4
Row 5
Row 6


After fetchmany(3)

Fetched:
Row 1
Row 2
Row 3

Remaining:
Row 4
Row 5
Row 6
        

A very important point is that fetching records changes the current Cursor position in the result set. The next fetch operation starts from Row 4.

Row 1  ✓ Fetched
Row 2  ✓ Fetched
Row 3  ✓ Fetched

------------------

Row 4  ← Next Cursor Position
Row 5
Row 6
        

Calling fetchmany() Multiple Times

fetchmany() can be called multiple times on the same result set:

data1 = cursor.fetchmany(3)
data2 = cursor.fetchmany(3)
        

The first call retrieves Rows 1, 2 and 3. The second call continues from the current Cursor position and retrieves Rows 4, 5 and 6.

Result Set
   │
   ├── Row 1 ─┐
   ├── Row 2  ├── First fetchmany(3)
   ├── Row 3 ─┘
   │
   ├── Row 4 ─┐
   ├── Row 5  ├── Second fetchmany(3)
   └── Row 6 ─┘
        
🐍Code Cell
1import cx_Oracle
2 
3try:
4 con = cx_Oracle.connect('scott/tiger@localhost')
5 cursor = con.cursor()
6 
7 cursor.execute("select * from employees")
8 
9 data1 = cursor.fetchmany(3)
10 
11 print("First Batch:")
12 
13 for row in data1:
14 print(row)
15 
16 data2 = cursor.fetchmany(3)
17 
18 print("Second Batch:")
19 
20 for row in data2:
21 print(row)
22 
23except cx_Oracle.DatabaseError as e:
24 print("There is a problem with sql :", e)
25 
26finally:
27 if cursor:
28 cursor.close()
29 
30 if con:
31 con.close()
Output
First Batch:
(100, 'Sachin', 1000, 'Mumbai')
(200, 'Dhoni', 2000, 'Ranchi')
(300, 'Kohli', 3000, 'Delhi')

Second Batch:
(400, 'Rohit', 4000, 'Mumbai')
(500, 'Rahul', 5000, 'Bangalore')
(600, 'Hardik', 6000, 'Baroda')

fetchmany() — Fewer or No Rows Remaining

The number passed to fetchmany() represents the maximum number of rows requested.

Suppose only two rows remain:

Row 5
Row 6
        

and we execute:

data = cursor.fetchmany(3)
        

Only the two remaining records are returned.

Requested = 3
Available = 2

Returned = 2
        

fetchmany() does not create an error simply because fewer rows are available.

Example — Fewer Rows than Requested

Suppose five employees exist and we fetch records in groups of three.

Total Records = 5
Batch Size    = 3
        

First Call

cursor.fetchmany(3)

Returns:
Row 1
Row 2
Row 3
        

Second Call

cursor.fetchmany(3)

Returns:
Row 4
Row 5
        

Although three records were requested, only two records remained.

What Happens When No Records Remain?

After all records have been fetched, another call to fetchmany() returns an empty collection:

data = []
        

Example — Complete Batch Fetching

Suppose there are seven employee records and the batch size is three:

fetchmany(3) → Row 1, Row 2, Row 3
fetchmany(3) → Row 4, Row 5, Row 6
fetchmany(3) → Row 7
fetchmany(3) → []
        

This shows how fetchmany() can be used to process a result set in batches.

App11 — Fetch All Records in Batches

We can repeatedly call fetchmany() until it returns an empty collection:

while True:
    data = cursor.fetchmany(3)

    if not data:
        break

    for row in data:
        print(row)
        

This approach retrieves employee records in groups of three until the complete result set has been processed.

                    START
                      │
                      ▼
             Execute SELECT Query
                      │
                      ▼
               fetchmany(3)
                      │
                      ▼
               data Available?
                 /                         Yes           No
                │             │
                ▼             ▼
          for row in data    break
                │             │
                ▼             │
            print(row)        │
                │             │
                ▼             │
         Process All Rows     │
           in Current Batch   │
                │             │
                └─────┐       │
                      │       │
                      ▼       │
               fetchmany(3)   │
                      │       │
                      └───────┘
                          │
                          ▼
                         END
        
🐍Code Cell
1import cx_Oracle
2 
3try:
4 con = cx_Oracle.connect('scott/tiger@localhost')
5 cursor = con.cursor()
6 
7 cursor.execute("select * from employees")
8 
9 while True:
10 
11 data = cursor.fetchmany(3)
12 
13 if not data:
14 break
15 
16 for row in data:
17 print(row)
18 
19except cx_Oracle.DatabaseError as e:
20 print("There is a problem with sql :", e)
21 
22finally:
23 if cursor:
24 cursor.close()
25 
26 if con:
27 con.close()
Output
No output captured.

App11 — Complete Program with Comments

The complete App11 program with comments for each step:

🐍Code Cell
1# Import Oracle Database module
2import cx_Oracle
3 
4try:
5 # Establish connection with Oracle Database
6 con = cx_Oracle.connect('scott/tiger@localhost')
7 
8 # Create Cursor object
9 cursor = con.cursor()
10 
11 # Execute SELECT query
12 cursor.execute("select * from employees")
13 
14 # Fetch maximum 3 employee records
15 data = cursor.fetchmany(3)
16 
17 # Process every fetched employee
18 for row in data:
19 
20 # Display employee record
21 print(row)
22 
23except cx_Oracle.DatabaseError as e:
24 
25 # Rollback if required
26 if con:
27 con.rollback()
28 
29 # Display Database error
30 print("There is a problem with sql :", e)
31 
32finally:
33 
34 # Close Cursor
35 if cursor:
36 cursor.close()
37 
38 # Close Database connection
39 if con:
40 con.close()
Output
No output captured.

fetchone() vs fetchmany() vs fetchall()

All three methods work with records produced by a SELECT query, but they differ in how many rows they retrieve at one time.

Feature fetchone() fetchmany() fetchall()
Purpose Fetch one row Fetch specified number of rows Fetch all remaining rows
Example fetchone() fetchmany(3) fetchall()
Return Single row Collection of rows Collection of rows
No More Rows None Empty collection Empty collection
Batch Size 1 Specified by programmer All remaining rows
Large Result Sets Can process one by one Useful for batch processing Can require more memory

Visual Comparison

Result Set:

R1  R2  R3  R4  R5  R6  R7
│
├── fetchone()
│      │
│      └── R1
│
├── fetchmany(3)
│      │
│      └── R1 R2 R3
│
└── fetchall()
       │
       └── R1 R2 R3 R4 R5 R6 R7
        

fetchall() is simple when we want to retrieve all records together. However, it retrieves all remaining rows into memory. If a query returns a very large number of records, processing records in smaller batches with fetchmany() or one by one with fetchone() can be more memory-friendly.

Methods Used

Method Purpose
connect() Establishes a connection with Oracle Database
cursor() Creates a Cursor object
execute() Executes the SELECT query
fetchone() Retrieves one row at a time from the result set
fetchmany(size) Retrieves up to the specified number of rows
fetchall() Retrieves all remaining records
rollback() Rolls back uncommitted changes when applicable
close() Closes Database resources
📝 Key Takeaways
  • The SQL SELECT statement retrieves data from a table without modifying it
  • fetchone() returns one row at a time and returns None when no more rows remain
  • fetchall() returns all remaining rows as a collection and returns an empty collection when no rows exist
  • fetchmany(size) returns up to the specified number of rows and continues from the current cursor position
  • SELECT does not require commit(), while INSERT, UPDATE, and DELETE normally do

🧠 Test Your Knowledge

10 Questions
Progress: 0 / 10