Python sqlite3 cursor has no attribute commit
Categories:
Understanding and Resolving 'sqlite3.Cursor' object has no attribute 'commit'

Learn why you encounter the 'sqlite3.Cursor' object has no attribute 'commit' error in Python and how to correctly commit transactions to your SQLite database.
When working with SQLite databases in Python using the sqlite3
module, a common pitfall for newcomers is attempting to call the commit()
method directly on a cursor
object. This action invariably leads to an AttributeError: 'sqlite3.Cursor' object has no attribute 'commit'
. This article will clarify why this error occurs and, more importantly, demonstrate the correct way to commit your database transactions, ensuring your changes are permanently saved.
The Role of Connection vs. Cursor
To understand why cursor.commit()
fails, it's crucial to differentiate between the Connection
object and the Cursor
object in sqlite3
. The Connection
object represents the actual link to your SQLite database file. It's responsible for managing transactions, including committing or rolling back changes. The Cursor
object, on the other hand, is used to execute SQL queries and fetch results. It acts as an intermediary, allowing you to interact with the database through the established connection.
flowchart TD A[Python Application] --> B["sqlite3.connect('database.db')"]; B --> C[Connection Object]; C --> D["connection.cursor() - Creates Cursor"]; D --> E[Cursor Object]; E --> F["cursor.execute(SQL Query)"]; F --> G["Database Operations (INSERT, UPDATE, DELETE)"]; G --> H["connection.commit() - Saves Changes"]; H --> I[Database File]; G -- "No commit" --> J["Changes not saved (Rollback on close)"];
Flow of interaction between Python, Connection, Cursor, and Database
As the diagram illustrates, the Cursor
object is for executing queries, while the Connection
object holds the responsibility for transaction management. When you execute an INSERT
, UPDATE
, or DELETE
statement, these changes are initially staged within the transaction. They are not permanently written to the database file until the commit()
method is called on the Connection
object.
Correctly Committing Transactions
The solution to the AttributeError
is straightforward: always call commit()
on the Connection
object, not the Cursor
object. It's also best practice to use a try...finally
block or a with
statement to ensure that your connection is properly closed, even if errors occur.
import sqlite3
# Establish a connection to the database
conn = sqlite3.connect('example.db')
# Create a cursor object
cursor = conn.cursor()
try:
# Execute an SQL command
cursor.execute('''
CREATE TABLE IF NOT EXISTS users (
id INTEGER PRIMARY KEY,
name TEXT NOT NULL,
email TEXT NOT NULL UNIQUE
)
''')
cursor.execute("INSERT INTO users (name, email) VALUES (?, ?)", ('Alice', 'alice@example.com'))
cursor.execute("INSERT INTO users (name, email) VALUES (?, ?)", ('Bob', 'bob@example.com'))
# Commit the changes to the database (on the connection object!)
conn.commit()
print("Data inserted and committed successfully.")
except sqlite3.Error as e:
print(f"An error occurred: {e}")
# Rollback changes if an error occurs
conn.rollback()
print("Transaction rolled back.")
finally:
# Close the connection
conn.close()
print("Connection closed.")
with
statement for database connections is highly recommended. It automatically handles committing changes (if no exceptions occur) and closing the connection, simplifying your code and reducing the chance of resource leaks.import sqlite3
# Using 'with' statement for automatic connection management
try:
with sqlite3.connect('example.db') as conn:
cursor = conn.cursor()
cursor.execute("INSERT INTO users (name, email) VALUES (?, ?)", ('Charlie', 'charlie@example.com'))
cursor.execute("INSERT INTO users (name, email) VALUES (?, ?)", ('David', 'david@example.com'))
# No explicit conn.commit() needed here, 'with' handles it on successful exit
print("Data inserted successfully using 'with' statement.")
except sqlite3.Error as e:
print(f"An error occurred: {e}")
# 'with' statement also handles rollback on exception
print("Transaction rolled back by 'with' statement.")
# Verify data
with sqlite3.connect('example.db') as conn:
cursor = conn.cursor()
cursor.execute("SELECT * FROM users")
rows = cursor.fetchall()
print("\nUsers in database:")
for row in rows:
print(row)
When is commit()
not needed?
By default, sqlite3
operates in DEFERRED
transaction mode. This means changes are not written to disk until commit()
is called. However, you can change this behavior. If you set isolation_level=None
when connecting, sqlite3
will operate in autocommit mode. In this mode, every statement is automatically committed, and you won't need to call conn.commit()
explicitly. While convenient for simple scripts, it can be less efficient for multiple operations and doesn't allow for easy transaction rollback.
import sqlite3
# Connect with autocommit mode
conn_autocommit = sqlite3.connect('example_autocommit.db', isolation_level=None)
cursor_autocommit = conn_autocommit.cursor()
try:
cursor_autocommit.execute('''
CREATE TABLE IF NOT EXISTS products (
id INTEGER PRIMARY KEY,
name TEXT NOT NULL,
price REAL
)
''')
cursor_autocommit.execute("INSERT INTO products (name, price) VALUES (?, ?)", ('Laptop', 1200.00))
# Changes are automatically committed after each execute in autocommit mode
print("Product inserted in autocommit mode.")
cursor_autocommit.execute("INSERT INTO products (name, price) VALUES (?, ?)", ('Mouse', 25.50))
print("Another product inserted in autocommit mode.")
except sqlite3.Error as e:
print(f"An error occurred in autocommit mode: {e}")
finally:
conn_autocommit.close()
print("Autocommit connection closed.")
# Verify data in autocommit database
with sqlite3.connect('example_autocommit.db') as conn:
cursor = conn.cursor()
cursor.execute("SELECT * FROM products")
rows = cursor.fetchall()
print("\nProducts in autocommit database:")
for row in rows:
print(row)
conn.commit()
(or using the with
statement) is generally preferred for robust applications, as it provides better control over data integrity and performance.