The cursor class

MariaDB Connector/Python Cursor Object

Cursor Parameters

Cursors are created using the connection.cursor() method and accept the following optional parameters:

Result Format Parameters

  • buffered (bool) - Buffer all results immediately in memory. When True (default), all rows are fetched and stored in memory. When False, results are streamed from the server, reducing memory usage for large result sets. Default: True

  • named_tuple (bool) - Return rows as named tuples instead of regular tuples. Allows accessing columns by name (e.g., row.column_name). Default: False

  • dictionary (bool) - Return rows as dictionaries instead of tuples. Allows accessing columns by name (e.g., row['column_name']). Default: False

  • native_object (bool) - Return native Python objects for certain database types. Default: False

Protocol Parameters

  • binary (bool) - Use binary protocol (prepared statements) for this cursor. Overrides the connection-level binary setting. When True, uses COM_STMT_PREPARE + COM_STMT_EXECUTE for better performance with repeated queries. Default: Inherits from connection

Cursor Examples

Basic cursor:

import mariadb

conn = mariadb.connect("mariadb://user:password@localhost/mydb")
cursor = conn.cursor()
cursor.execute("SELECT id, name FROM users")
for row in cursor:
    print(f"ID: {row[0]}, Name: {row[1]}")
cursor.close()
conn.close()

Unbuffered cursor for large result sets:

Dictionary cursor:

Named tuple cursor:

Binary protocol cursor:

Combined parameters:

Cursor methods

Cursor.callproc(sp: str, data: Sequence[Any] = ()) -> None

Executes a stored procedure sp. The data sequence must contain an entry for each parameter the procedure expects.

Input/Output or Output parameters have to be retrieved by .fetch methods, the .sp_outparams attribute indicates if the result set contains output parameters.

Arguments: : - sp: Name of stored procedure.

  • data: Optional sequence containing data for placeholder : substitution.

Example:

Cursor.execute(sql: str, data: Optional[Union[Sequence[Any], dict]] = None, buffered: Optional[bool] = None) -> None

Prepare and execute a SQL statement.

Parameters may be provided as sequence or mapping and will be bound to variables in the operation. Variables are specified as question marks (paramstyle ='qmark'), however for compatibility reasons MariaDB Connector/Python also supports the 'format' and 'pyformat' paramstyles with the restriction, that different paramstyles can't be mixed within a statement.

A reference to the operation will be retained by the cursor.

Since version 2.0: If the cursor was created with binary=True, the statement uses the MariaDB binary protocol (prepared statements). With prepared statement caching enabled (default), the first execution prepares the statement and subsequent executions reuse the cached prepared statement for better performance.

By default execute() method generates a buffered result unless the optional parameter buffered was set to False or the cursor was generated as an unbuffered cursor.

Protocol Selection (Version 2.0):

  • Text protocol (default): Standard SQL execution, predictable behavior

  • Binary protocol (binary=True): Uses COM_STMT_PREPARE + COM_STMT_EXECUTE

  • Dict parameters: Always use text protocol for named parameter substitution

Cursor.executemany(sql: str, data: Sequence[Union[Sequence[Any], dict]], buffered: Optional[bool] = None) -> None

Prepare a database operation (INSERT,UPDATE,REPLACE or DELETE statement) and execute it against all parameter found in sequence.

Exactly behaves like .execute() but accepts a list of tuples, where each tuple represents data of a row within a table. .executemany() only supports DML (insert, update, delete) statements.

If the SQL statement contains a RETURNING clause, executemany() returns a result set containing the values for columns listed in the RETURNING clause.

Example:

The following example will insert 3 rows:

To insert special values like NULL or a column default, you need to specify indicators:

  • INDICATOR.NULL is used for NULL values

  • INDICATOR.IGNORE is used to skip update of a column.

  • INDICATOR.DEFAULT is used for a default value (insert/update)

  • INDICATOR.ROW is used to skip update/insert of the entire row.

NOTE

  • All values for a column must have the same data type.

  • Indicators can only be used when connecting to a MariaDB Server 10.2 or newer. MySQL servers don’t support this feature.

Cursor.fetchall() -> List[Any]

Fetch all remaining rows of a query result, returning them as a sequence of sequences (e.g. a list of tuples).

An exception will be raised if the previous call to execute() didn't produce a result set or execute() wasn't called before.

Example:

Cursor.fetchmany(size: Optional[int] = None) -> List[Any]

Fetch the next set of rows of a query result, returning a sequence of sequences (e.g. a list of tuples). An empty sequence is returned when no more rows are available.

The number of rows to fetch per call is specified by the parameter. If it is not given, the cursor's arraysize determines the number of rows to be fetched. The method should try to fetch as many rows as indicated by the size parameter. If this is not possible due to the specified number of rows not being available, fewer rows may be returned.

An exception will be raised if the previous call to execute() didn't produce a result set or execute() wasn't called before.

Example:

Cursor.fetchone() -> Optional[Any]

Fetch the next row of a query result set, returning a single sequence, or None if no more data is available.

An exception will be raised if the previous call to execute() didn't produce a result set or execute() wasn't called before.

Example:

Cursor.next() -> Optional[Any]

Return the next row from the currently executed SQL statement using the same semantics as .fetchone().

Cursor.nextset() -> Optional[bool]

Will make the cursor skip to the next available result set, discarding any remaining rows from the current set.

Cursor.scroll(value: int, mode: str = 'relative') -> None

Scroll the cursor in the result set to a new position according to mode.

If mode is “relative” (default), value is taken as offset to the current position in the result set, if set to absolute, value states an absolute target position.

Cursor.setinputsizes() -> None

Required by PEP-249. Does nothing in MariaDB Connector/Python

Cursor.setoutputsize() -> None

Required by PEP-249. Does nothing in MariaDB Connector/Python

Cursor attributes

Cursor.arraysize: int

(read/write)

The number of rows to fetch at a time with .fetchmany().

This read/write attribute defaults to 1 meaning to fetch a single row at a time.

Example:

Cursor.buffered: bool

(read-only)

Controls whether result sets are buffered in memory or streamed from the server.

Buffered (True):

  • All result rows are immediately fetched and stored in client memory

  • The entire result set is transferred at once

  • Connection is freed immediately after execute()

  • Multiple cursors can be active on the same connection

  • Higher memory usage for large result sets

  • Better for small to medium result sets

Unbuffered (False, default in 2.0):

  • Results are streamed row-by-row from the server

  • Only the current row is kept in memory

  • Connection remains blocked until all rows are fetched

  • Only one unbuffered cursor can be active per connection

  • Lower memory usage - ideal for large result sets

  • Must fetch all rows before executing another query on the same connection

Example:

Best Practices:

Cursor.close() -> None

Close the cursor and free resources. After closing, the cursor cannot be used anymore.

Example:

Cursor.connection: Connection

(read-only)

Returns the reference to the connection object on which the cursor was created.

Example:

Cursor.description: Optional[Sequence[Tuple]]

(read-only)

This read-only attribute is a sequence of 11-item tuples. Each tuple contains information describing one result column:

  1. name - Column name

  2. type_code - Column type code

  3. display_size - Display size

  4. internal_size - Internal size

  5. precision - Precision

  6. scale - Scale

  7. null_ok - Whether NULL values are allowed

  8. field_flags - Field flags (extension to PEP-249)

  9. table_name - Table name (extension to PEP-249)

  10. original_column_name - Original column name (extension to PEP-249)

  11. original_table_name - Original table name (extension to PEP-249)

This attribute will be None for operations that do not return rows or if the cursor has not had an operation invoked via the .execute*() method yet.

Example:

Checking BLOB vs TEXT fields:

Cursor.lastrowid

Returns the ID generated by a query on a table with a column having the AUTO_INCREMENT attribute or the value for the last usage of LAST_INSERT_ID().

If the last query wasn’t an INSERT or UPDATE statement or if the modified table does not have a column with the AUTO_INCREMENT attribute and LAST_INSERT_ID was not used, the returned value will be None

Cursor.metadata: Optional[Dict[str, List]]

(read-only)

Similar to the description property, this property returns a dictionary with complete metadata for all columns in the result set.

Each dictionary key contains a list of values, one for each column in the result set.

Dictionary Keys:

  • catalog - Catalog name (always 'def')

  • schema - Current schema/database name

  • field - Column alias name, or original column name if no alias

  • org_field - Original column name

  • table - Table alias name, or original table name if no alias

  • org_table - Original table name

  • type - Column type (values from mariadb.constants.FIELD_TYPE)

  • charset - Character set (e.g., 'utf8mb4' or 'binary')

  • length - Maximum length of the column

  • max_length - Maximum length of data in the result set

  • decimals - Number of decimals for numeric types

  • flags - Field flags (values from mariadb.constants.FIELD_FLAG)

  • ext_type_or_format - Extended data type (values from mariadb.constants.EXT_FIELD_TYPE)

Since version 1.1.8

Example:

Detecting Extended Types (JSON, UUID, INET, Geometry):

Cursor.sp_outparams: bool

(read-only)

Indicates if the current result set contains OUT or INOUT parameters from a previously executed stored procedure.

When calling a stored procedure with OUT or INOUT parameters using callproc() or execute(), the output parameters are returned as a separate result set. This attribute is True when the current result set contains these output parameters, and False otherwise.

Example:

Example with Multiple Result Sets:

Using with Binary Protocol:

Cursor.rowcount: int

(read-only)

Returns the number of rows that the last execute*() method produced (for DQL statements like SELECT) or affected (for DML statements like UPDATE, INSERT, DELETE).

Return Values:

  • Positive number - Number of rows returned (SELECT) or affected (INSERT/UPDATE/DELETE)

  • -1 - No execute*() has been performed, or rowcount cannot be determined

  • 0 - Statement executed but no rows were affected/returned

Important Notes:

  • For unbuffered cursors (default in 2.0), the exact row count is only available after all rows have been fetched

  • For buffered cursors, the row count is immediately available after execute()

  • For INSERT/UPDATE/DELETE, the row count is always immediately available

Examples:

Unbuffered Cursor (Default):

Buffered Cursor:

DML Statements (INSERT/UPDATE/DELETE):

Batch Operations with executemany():

Practical Use Case - Verify Operation Success:

Cursor.statement: Optional[str]

(read-only)

Returns the last SQL statement that was executed by the cursor.

Example:

Cursor.warnings: int

(read-only)

Returns the number of warnings from the last executed statement, or zero if there are no warnings.

Note: Detailed warning messages can be retrieved using the connection.show_warnings() method.

Example:

Cursor.rownumber: Optional[int]

(read-only)

Returns the current 0-based index of the cursor in the result set, or None if no result set is available.

This property tracks the position within the current result set as rows are fetched.

Example:

Cursor.field_count: int

(read-only)

Returns the number of columns in the current result set, or 0 if there is no result set.

Example:

Cursor.closed: bool

(read-only)

Returns True if the cursor is closed, False otherwise.

A cursor is considered closed if either the cursor itself was closed or the parent connection was closed.

Example:

Connection closure also closes cursors:

spinner

Last updated

Was this helpful?