Python sqlite3.PARSE_DECLTYPES 常量
上次修改时间:2025 年 4 月 15 日
这份全面的指南探讨了 Python 的 sqlite3.PARSE_DECLTYPES
常量,它可以在从 SQLite 数据库检索数据时实现自动类型转换。我们将涵盖它的用法、优点和实际示例。
基本定义
sqlite3.PARSE_DECLTYPES
常量与 sqlite3.connect
一起使用,以启用基于列声明的类型转换。设置后,SQLite 将尝试将值转换为与列的声明类型匹配的 Python 类型。
主要特征:它与 detect_types
参数一起使用,支持标准的 Python 类型,如 datetime.date
,并且需要在表定义中进行正确的列类型声明。
PARSE_DECLTYPES 的基本用法
这是一个简单的示例,演示如何使用 PARSE_DECLTYPES
自动转换日期值类型。
import sqlite3 import datetime # Connect with PARSE_DECLTYPES enabled with sqlite3.connect(':memory:', detect_types=sqlite3.PARSE_DECLTYPES) as conn: cursor = conn.cursor() # Create table with DATE type declaration cursor.execute('''CREATE TABLE events (id INTEGER PRIMARY KEY, name TEXT, event_date DATE)''') # Insert current date today = datetime.date.today() cursor.execute("INSERT INTO events (name, event_date) VALUES (?, ?)", ('Meeting', today)) # Retrieve and verify type cursor.execute("SELECT event_date FROM events") retrieved_date = cursor.fetchone()[0] print(f"Type of retrieved date: {type(retrieved_date)}") # datetime.date print(f"Date matches original: {retrieved_date == today}") # True
此示例展示了 PARSE_DECLTYPES
如何自动将 SQLite DATE 值转换为 Python datetime.date
对象。转换发生在数据检索期间。
请注意正确声明列类型(在本例中为 DATE)的重要性,以便转换正常工作。如果没有类型声明,则不会发生转换。
使用 DATETIME 值
当在表架构中正确声明时,PARSE_DECLTYPES
也可以处理 datetime 值。
import sqlite3 from datetime import datetime with sqlite3.connect(':memory:', detect_types=sqlite3.PARSE_DECLTYPES) as conn: cursor = conn.cursor() # Create table with TIMESTAMP type declaration cursor.execute('''CREATE TABLE logs (id INTEGER PRIMARY KEY, message TEXT, created_at TIMESTAMP)''') # Insert current datetime now = datetime.now() cursor.execute("INSERT INTO logs (message, created_at) VALUES (?, ?)", ('System started', now)) # Retrieve and verify datetime cursor.execute("SELECT created_at FROM logs") retrieved_dt = cursor.fetchone()[0] print(f"Type: {type(retrieved_dt)}") # datetime.datetime print(f"Value: {retrieved_dt}") print(f"Microseconds preserved: {retrieved_dt.microsecond == now.microsecond}")
此示例演示了将 TIMESTAMP 列自动转换为 Python datetime.datetime
对象。转换保留所有 datetime 组件,包括微秒。
关键要求是在表架构中将列声明为 TIMESTAMP。 诸如 DATETIME 之类的其他声明也适用于此转换。
与 PARSE_COLNAMES 结合使用
PARSE_DECLTYPES
可以与 PARSE_COLNAMES
结合使用,以实现更灵活的类型转换场景。
import sqlite3 from decimal import Decimal # Register converter for DECIMAL type sqlite3.register_converter("DECIMAL", lambda x: Decimal(x.decode('utf-8'))) with sqlite3.connect(':memory:', detect_types=sqlite3.PARSE_DECLTYPES | sqlite3.PARSE_COLNAMES) as conn: cursor = conn.cursor() # Create table with mixed types cursor.execute('''CREATE TABLE products (id INTEGER PRIMARY KEY, name TEXT, price DECIMAL, weight REAL)''') # Insert data with decimal value cursor.execute("INSERT INTO products (name, price, weight) VALUES (?, ?, ?)", ('Laptop', '1299.99', 2.5)) # Query with type hints in column names cursor.execute('''SELECT price AS "price [DECIMAL]", weight AS "weight [REAL]" FROM products''') product = cursor.fetchone() print(f"Price type: {type(product[0])}") # decimal.Decimal print(f"Weight type: {type(product[1])}") # float
此示例展示了如何结合使用两种解析模式。 PARSE_DECLTYPES
处理来自列声明的 DECIMAL 类型,而 PARSE_COLNAMES
允许在查询中使用类型提示。
我们还演示了为 DECIMAL 类型注册自定义转换器,该转换器将字符串值转换为 Python Decimal
对象。
处理 NULL 值
PARSE_DECLTYPES
正确处理 NULL 值,无需转换尝试,从而保持 Python 的 None
作为数据库 NULL。
import sqlite3 from datetime import date with sqlite3.connect(':memory:', detect_types=sqlite3.PARSE_DECLTYPES) as conn: cursor = conn.cursor() cursor.execute('''CREATE TABLE tasks (id INTEGER PRIMARY KEY, description TEXT, due_date DATE, completed DATE)''') # Insert data with NULL date cursor.execute('''INSERT INTO tasks (description, due_date, completed) VALUES (?, ?, ?)''', ('Write report', date(2025, 6, 15), None)) # Retrieve and check NULL handling cursor.execute("SELECT due_date, completed FROM tasks") due, completed = cursor.fetchone() print(f"Due date type: {type(due)}") # datetime.date print(f"Completed type: {type(completed)}") # NoneType print(f"Is completed None: {completed is None}") # True
此示例演示了,即使对于使用 DATE 类型声明的列,类型列中的 NULL 值在检索时仍为 Python None
。
类型转换仅针对非 NULL 值发生,从而使该行为对于数据库架构中的可空列是安全的。
自定义类型转换
您可以注册自定义转换器,以将 PARSE_DECLTYPES
扩展到您自己的 Python 类型。
import sqlite3 import json from typing import Dict # Define custom type and converter def dict_converter(value: bytes) -> Dict: return json.loads(value.decode('utf-8')) # Register the converter sqlite3.register_converter("JSON", dict_converter) with sqlite3.connect(':memory:', detect_types=sqlite3.PARSE_DECLTYPES) as conn: cursor = conn.cursor() # Create table with JSON type cursor.execute('''CREATE TABLE configs (id INTEGER PRIMARY KEY, name TEXT, settings JSON)''') # Insert dictionary as JSON settings = {'theme': 'dark', 'notifications': True, 'timeout': 30} cursor.execute("INSERT INTO configs (name, settings) VALUES (?, ?)", ('User Preferences', json.dumps(settings))) # Retrieve and verify automatic conversion cursor.execute("SELECT settings FROM configs") retrieved = cursor.fetchone()[0] print(f"Type: {type(retrieved)}") # dict print(f"Theme: {retrieved['theme']}") # dark print(f"Original == Retrieved: {settings == retrieved}") # True
此示例展示了如何通过注册自定义转换器来处理 SQLite 中的 JSON 数据。 JSON 列类型会自动转换为 Python 字典。
转换器函数接收值作为字节,并且必须返回转换后的 Python 对象。 在这里,我们使用 JSON 序列化进行转换。
使用 Time 值
PARSE_DECLTYPES
也可以将 TIME 列转换为 Python datetime.time
对象。
import sqlite3 from datetime import time with sqlite3.connect(':memory:', detect_types=sqlite3.PARSE_DECLTYPES) as conn: cursor = conn.cursor() # Create table with TIME type cursor.execute('''CREATE TABLE schedule (id INTEGER PRIMARY KEY, event TEXT, start_time TIME, end_time TIME)''') # Insert time values start = time(9, 30) end = time(17, 0) cursor.execute('''INSERT INTO schedule (event, start_time, end_time) VALUES (?, ?, ?)''', ('Workday', start, end)) # Retrieve and verify times cursor.execute("SELECT start_time, end_time FROM schedule") retrieved_start, retrieved_end = cursor.fetchone() print(f"Start type: {type(retrieved_start)}") # datetime.time print(f"End type: {type(retrieved_end)}") # datetime.time print(f"Start matches: {retrieved_start == start}") # True print(f"End matches: {retrieved_end == end}") # True
此示例演示了将 TIME 列自动转换为 Python datetime.time
对象。 转换保留所有时间组件。
与其他时间类型一样,必须在表架构中将列正确声明为 TIME,以便转换自动工作。
最佳实践
- 始终声明列类型: PARSE_DECLTYPES 依赖于正确的类型声明
- 注册自定义转换器: 扩展功能以满足您的特定需求
- 正确处理 NULL: 使用可空列进行测试
- 与 PARSE_COLNAMES 结合使用: 为了获得最大的灵活性
- 记录类型转换: 使该行为在您的代码库中清晰明了
资料来源
作者
列出所有 Python 教程。