ZetCode

Python sqlite3.NotSupportedError Exception

Last modified April 15, 2025

This comprehensive guide explores Python's sqlite3.NotSupportedError exception, which occurs when attempting unsupported SQLite operations. We'll cover when it's raised, how to handle it, and practical examples.

Basic Definitions

The sqlite3.NotSupportedError is a subclass of sqlite3.Error that indicates an operation isn't supported by SQLite. It's raised when trying to use features not implemented in SQLite.

Key characteristics: it signals API misuse or unsupported SQL features. The error typically occurs with advanced database features that SQLite doesn't implement.

Attempting to Use Savepoints

SQLite didn't support savepoints in older versions. This example shows the error when trying to use them with an unsupported SQLite version.

savepoints.py
import sqlite3

try:
    with sqlite3.connect(':memory:') as conn:
        cursor = conn.cursor()
        # Try to create a savepoint (not supported in older SQLite)
        cursor.execute("SAVEPOINT test_savepoint")
except sqlite3.NotSupportedError as e:
    print(f"Savepoints not supported: {e}")

This code attempts to create a savepoint, which might fail on older SQLite versions. The NotSupportedError is caught and handled gracefully.

Modern SQLite versions support savepoints, but this demonstrates how to handle cases where features aren't available in your environment.

Using Unsupported Column Types

SQLite has a limited set of column types. Attempting to use unsupported types raises NotSupportedError.

column_types.py
import sqlite3

try:
    with sqlite3.connect(':memory:') as conn:
        cursor = conn.cursor()
        # Try to use an unsupported column type
        cursor.execute("CREATE TABLE test (id UUID)")
except sqlite3.NotSupportedError as e:
    print(f"UUID type not supported: {e}")

SQLite doesn't natively support UUID as a column type. The example shows how to catch this limitation. You'd need to store UUIDs as TEXT or BLOB instead.

This pattern helps write portable code that works across different database backends with varying type support.

Attempting to Alter Column Types

SQLite has limited ALTER TABLE support. Trying to modify column types might raise NotSupportedError.

alter_column.py
import sqlite3

with sqlite3.connect(':memory:') as conn:
    cursor = conn.cursor()
    cursor.execute("CREATE TABLE test (id INTEGER, name TEXT)")
    
    try:
        # Try to change column type (limited support in SQLite)
        cursor.execute("ALTER TABLE test ALTER COLUMN name TYPE VARCHAR(100)")
    except sqlite3.NotSupportedError as e:
        print(f"Column type alteration not supported: {e}")
        # Workaround: create new table and copy data

SQLite's ALTER TABLE only supports renaming tables and adding columns. This example catches the unsupported operation and suggests a workaround.

Understanding these limitations helps design more robust database schemas from the start, avoiding costly migrations later.

Using Unsupported SQL Syntax

SQLite doesn't implement all SQL standard features. Some syntax triggers NotSupportedError.

unsupported_syntax.py
import sqlite3

try:
    with sqlite3.connect(':memory:') as conn:
        cursor = conn.cursor()
        # Try to use FULL OUTER JOIN (not supported in SQLite)
        cursor.execute("""
            SELECT * FROM table1
            FULL OUTER JOIN table2 ON table1.id = table2.id
        """)
except sqlite3.NotSupportedError as e:
    print(f"FULL OUTER JOIN not supported: {e}")
    # Workaround: combine LEFT and RIGHT JOINs with UNION

SQLite lacks FULL OUTER JOIN support. The example catches this and suggests an alternative approach using UNION of LEFT and RIGHT JOINs.

This demonstrates how to handle SQL dialect differences when writing portable database code.

Attempting to Use Window Functions

Window functions were added in SQLite 3.25.0. Earlier versions raise NotSupportedError when attempting to use them.

window_functions.py
import sqlite3

try:
    with sqlite3.connect(':memory:') as conn:
        cursor = conn.cursor()
        cursor.execute("CREATE TABLE sales (id INTEGER, amount REAL)")
        
        # Try to use window function (requires SQLite ≥ 3.25.0)
        cursor.execute("""
            SELECT id, amount, 
                   SUM(amount) OVER (ORDER BY id) AS running_total
            FROM sales
        """)
except sqlite3.NotSupportedError as e:
    print(f"Window functions not supported: {e}")
    # Workaround: use subqueries or application-side calculation

This example attempts to use window functions which might not be available. The error is caught, and alternative approaches are suggested.

Checking SQLite version before using advanced features can prevent runtime errors in applications targeting multiple environments.

Using Unsupported Connection Parameters

Some connection parameters might not be supported in all SQLite versions, triggering NotSupportedError.

connection_params.py
import sqlite3

try:
    # Try to use URI connection (requires SQLite ≥ 3.7.13)
    with sqlite3.connect('file:test.db?mode=rwc&cache=shared', uri=True) as conn:
        cursor = conn.cursor()
        cursor.execute("SELECT 1")
except sqlite3.NotSupportedError as e:
    print(f"URI connections not supported: {e}")
    # Fall back to regular connection
    with sqlite3.connect('test.db') as conn:
        cursor = conn.cursor()
        cursor.execute("SELECT 1")

URI-style connections require newer SQLite versions. The example demonstrates graceful fallback to traditional connection when URIs aren't supported.

This pattern ensures your application works across different SQLite versions while taking advantage of newer features when available.

Attempting to Use Foreign Key Constraints

While SQLite supports foreign keys, they're disabled by default. Attempting to use them without enabling support might cause issues.

foreign_keys.py
import sqlite3

try:
    with sqlite3.connect(':memory:') as conn:
        cursor = conn.cursor()
        # Foreign key support must be enabled per-connection
        cursor.execute("PRAGMA foreign_keys = ON")
        
        cursor.execute("CREATE TABLE parent (id INTEGER PRIMARY KEY)")
        cursor.execute("""
            CREATE TABLE child (
                id INTEGER PRIMARY KEY,
                parent_id INTEGER REFERENCES parent(id)
            )
        """)
        
        # This should fail with foreign key violation
        cursor.execute("INSERT INTO child (parent_id) VALUES (999)")
        conn.commit()
except sqlite3.NotSupportedError as e:
    print(f"Foreign key constraints not supported: {e}")

This example shows proper foreign key usage. While not strictly a NotSupportedError case, it demonstrates related functionality that might fail in some SQLite configurations.

The example highlights the importance of enabling features and checking for support in your specific environment.

Best Practices

Source References

Author

My name is Jan Bodnar, and I am a passionate programmer with extensive programming experience. I have been writing programming articles since 2007. To date, I have authored over 1,400 articles and 8 e-books. I possess more than ten years of experience in teaching programming.

List all Python tutorials.