ZetCode

Python sqlite3.NotSupportedError 异常

上次修改时间:2025 年 4 月 15 日

这篇综合指南探讨了 Python 的 sqlite3.NotSupportedError 异常,当尝试不支持的 SQLite 操作时会发生此异常。我们将介绍何时引发此异常,如何处理它以及实际示例。

基本定义

sqlite3.NotSupportedErrorsqlite3.Error 的子类,表示 SQLite 不支持某项操作。当尝试使用 SQLite 中未实现的功能时会引发此异常。

主要特征:它表示 API 使用不当或不支持的 SQL 功能。该错误通常发生在 SQLite 未实现的高级数据库功能上。

尝试使用保存点

旧版本的 SQLite 不支持保存点。此示例显示了在使用不支持的 SQLite 版本时发生的错误。

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}")

此代码尝试创建一个保存点,这可能在旧版本的 SQLite 上失败。NotSupportedError 被捕获并妥善处理。

现代 SQLite 版本支持保存点,但这也演示了如何处理您的环境中无法使用的功能。

使用不支持的列类型

SQLite 具有有限的列类型集。尝试使用不支持的类型会引发 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 本身不支持 UUID 作为列类型。该示例演示了如何捕获此限制。您需要将 UUID 存储为 TEXT 或 BLOB 代替。

此模式有助于编写可在具有不同类型支持的不同数据库后端之间移植的代码。

尝试更改列类型

SQLite 对 ALTER TABLE 的支持有限。尝试修改列类型可能会引发 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 的 ALTER TABLE 仅支持重命名表和添加列。此示例捕获不支持的操作并提供了一种解决方法。

了解这些限制有助于从一开始就设计更健壮的数据库模式,从而避免以后进行代价高昂的迁移。

使用不支持的 SQL 语法

SQLite 未实现所有 SQL 标准功能。某些语法会触发 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 缺少 FULL OUTER JOIN 支持。该示例捕获了这一点,并建议使用 LEFT 和 RIGHT JOIN 的 UNION 的替代方法。

这演示了在编写可移植数据库代码时如何处理 SQL 方言的差异。

尝试使用窗口函数

窗口函数已在 SQLite 3.25.0 中添加。早期版本在尝试使用它们时会引发 NotSupportedError

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

此示例尝试使用可能不可用的窗口函数。该错误被捕获,并提出了替代方法。

在使用高级功能之前检查 SQLite 版本可以防止针对多个环境的应用程序中出现运行时错误。

使用不支持的连接参数

某些连接参数可能并非在所有 SQLite 版本中都受支持,从而触发 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 风格的连接需要较新的 SQLite 版本。该示例演示了当不支持 URI 时,如何优雅地回退到传统连接。

此模式确保您的应用程序可以在不同的 SQLite 版本上运行,同时在可用时利用更新的功能。

尝试使用外键约束

虽然 SQLite 支持外键,但默认情况下已禁用它们。尝试在不启用支持的情况下使用它们可能会导致问题。

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}")

此示例显示了正确的外键用法。虽然不是严格的 NotSupportedError 案例,但它演示了在某些 SQLite 配置中可能失败的相关功能。

该示例强调了启用功能以及检查特定环境中支持的重要性。

最佳实践

资料来源

作者

我叫 Jan Bodnar,是一位充满热情的程序员,拥有丰富的编程经验。自 2007 年以来,我一直在撰写编程文章。到目前为止,我已经撰写了超过 1,400 篇文章和 8 本电子书。我拥有超过十年的编程教学经验。

列出所有 Python 教程