Tipos de Datos SQLite en Python | Capítulo 3

SQLite implementa un sistema de clases de almacenamiento reducido. Nativamente, solo soporta cinco tipos: NULL, INTEGER, REAL, TEXT y BLOB. El módulo sqlite3 de Python gestiona la traducción bidireccional entre los tipos de la base de datos y las estructuras de CPython.

Mapeo Nativo Bidireccional

Esta conversión ocurre a nivel del puente C de la librería, garantizando una sobrecarga de rendimiento mínima:

Tipo PythonClase de Almacenamiento SQLite
NoneNULL
intINTEGER (hasta 64-bit con signo)
floatREAL (coma flotante IEEE de 8 bytes)
strTEXT (codificación UTF-8 por defecto)
bytesBLOB (datos binarios en crudo)

Gestión de Tipos Complejos (Adaptadores y Convertidores)

El desafío de ingeniería surge al persistir estructuras de datos comunes en Python que no tienen equivalente nativo, como datetime, UUID o diccionarios (dict).

Delegar la serialización a la lógica de negocio antes de cada inserción contamina el código y aumenta la probabilidad de inconsistencias de formato. La arquitectura correcta requiere registrar adaptadores (Python a SQLite) y convertidores (SQLite a Python) a nivel global de la librería.

Ejemplo de Producción: Datetime y JSON

Para garantizar ordenamiento temporal preciso en la base de datos y recuperación de objetos nativos en Python, los datetime deben almacenarse como cadenas ISO 8601 o timestamps UNIX. Para diccionarios, la estrategia es almacenar el JSON serializado como TEXT.

import sqlite3
import json
from datetime import datetime, timezone

# 1. Adaptadores (Python -> SQLite)
# Convierte un objeto datetime con zona horaria a formato ISO 8601 (TEXT)
sqlite3.register_adapter(
    datetime, 
    lambda dt: dt.astimezone(timezone.utc).isoformat()
)

# Convierte un dict de Python a una cadena JSON (TEXT)
sqlite3.register_adapter(
    dict, 
    lambda d: json.dumps(d)
)

# 2. Convertidores (SQLite -> Python)
# Intercepta columnas declaradas como "TIMESTAMP" y retorna un objeto datetime
sqlite3.register_converter(
    "TIMESTAMP", 
    lambda b: datetime.fromisoformat(b.decode('utf-8'))
)

# Intercepta columnas declaradas como "JSON" y retorna un dict de Python
sqlite3.register_converter(
    "JSON", 
    lambda b: json.loads(b.decode('utf-8'))
)

# 3. Implementación en la conexión
def get_typed_connection(db_path: str) -> sqlite3.Connection:
    """
    Retorna una conexión capaz de inferir tipos basándose 
    en la declaración de las columnas (PARSE_DECLTYPES).
    """
    return sqlite3.connect(
        db_path,
        # PARSE_DECLTYPES fuerza a SQLite a leer el tipo declarado en el CREATE TABLE
        # para aplicar el convertidor correspondiente durante los SELECTs.
        detect_types=sqlite3.PARSE_DECLTYPES
    )
Python

Consideración de rendimiento: Al usar detect_types=sqlite3.PARSE_DECLTYPES, la librería sqlite3 realiza un parseo adicional del esquema de la tabla en tiempo de ejecución durante los SELECT. Para aplicaciones con latencia ultrabaja extrema, este costo milisegundo puede ser relevante, pero en el 99% de las arquitecturas web o de microservicios, la ganancia en integridad de datos y limpieza de código justifica la decisión.

Dejar un comentario

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *

Scroll al inicio