Comprobar una consulta SQL escrita por IA frente a resultados de SQLite calculados a mano
Trata una consulta SQL generada por IA como un borrador y pruébala en una pequeña base de datos SQLite con respuestas conocidas. Compara el resultado de la IA con una tabla esperada calculada manualmente antes de usar la consulta con datos reales.
Contenido revisado 2026.09.20Incluye código de ejemplo
Ver el índice
La traducción se ha realizado con IA. Comprueba el código, las unidades y los valores junto con el original. La revisión por hablantes nativos de cada idioma aún no se ha completado. English
Para quién esEsta guía es para personas que usan IA para redactar SQL y quieren una prueba pequeña y reproducible antes de ejecutar la consulta sobre datos importantes.
Preparación
Python 3.12 y un comando de terminal que inicie esa versión.
Una carpeta de trabajo donde los scripts puedan crear carpetas dentro de outputs.
Conocimientos básicos de SELECT, JOIN, GROUP BY y funciones de agregación.
Solo se necesita la biblioteca estándar de Python: csv, pathlib y sqlite3.
01Define la pregunta de negocio antes de revisar el SQL
Supongamos que el requisito es: para cada cliente, informar el valor total de los pedidos PAID realizados durante agosto de 2026. Los clientes sin pedidos que cumplan las condiciones deben seguir apareciendo con un total de 0.
Un asistente de IA propone un INNER JOIN entre customers y orders, seguido de condiciones WHERE para status y date. La consulta parece razonable, pero el INNER JOIN elimina a los clientes que no tienen filas de pedido coincidentes. Esto incumple el requisito de incluir a los clientes con total cero.
02Crea una base de datos SQLite sintética
La siguiente base de datos es sintética y se creó específicamente para este artículo. Tiene tres clientes y seis pedidos seleccionados para probar estados pagados y no pagados, límites entre meses y un cliente sin pedidos PAID en agosto.
Ana tiene dos pedidos PAID en agosto: 40 y 60, por lo que su total es 100. Su pedido CANCELLED no cuenta. Ben tiene un pedido válido de agosto por valor de 25; su pedido de septiembre no cuenta. Cara solo tiene un pedido CANCELLED en agosto, por lo que debe seguir apareciendo con 0.
customer_id
customer_name
Total PAID esperado de agosto
1
Ana
100
2
Ben
25
3
Cara
0
El total general esperado es 125. Debe haber exactamente 3 filas de salida porque el requisito indica que todos los clientes deben aparecer.
04Compara la consulta de IA con una consulta revisada
La consulta de IA siguiente filtra los pedidos válidos en la cláusula WHERE después de un INNER JOIN. Cara no tiene ningún pedido PAID de agosto que coincida, por lo que desaparece por completo.
sql
SELECT
c.customer_id,
c.customer_name,
SUM(o.amount) AS august_paid_total
FROM customers AS c
JOIN orders AS o
ON o.customer_id = c.customer_id
WHERE o.status = 'PAID'
AND o.order_date >= '2026-08-01'
AND o.order_date < '2026-09-01'
GROUP BY c.customer_id, c.customer_name
ORDER BY c.customer_id;
La consulta revisada parte de todos los clientes y utiliza LEFT JOIN. Los filtros de pedidos se colocan dentro de la condición ON para conservar a los clientes sin coincidencias. COALESCE convierte el agregado NULL resultante en 0.
sql
SELECT
c.customer_id,
c.customer_name,
COALESCE(SUM(o.amount), 0) AS august_paid_total
FROM customers AS c
LEFT JOIN orders AS o
ON o.customer_id = c.customer_id
AND o.status = 'PAID'
AND o.order_date >= '2026-08-01'
AND o.order_date < '2026-09-01'
GROUP BY c.customer_id, c.customer_name
ORDER BY c.customer_id;
05Ejecuta ambas consultas y compáralas con las filas esperadas
Guarda el siguiente script como ai_sql_check.py. Ejecuta ambas consultas, compara sus resultados con la tabla esperada calculada a mano y escribe un informe CSV de revisión. No modifica la base de datos sintética.
python
import csv
import sqlite3
from pathlib import Path
DATABASE = Path("outputs") / "ai_sql_demo" / "orders.sqlite"
OUTPUT_DIR = Path("outputs") / "ai_sql_check_result"
REPORT = OUTPUT_DIR / "sql_check.csv"
AI_SQL = """
SELECT c.customer_id, c.customer_name, SUM(o.amount)
FROM customers AS c
JOIN orders AS o ON o.customer_id = c.customer_id
WHERE o.status = 'PAID'
AND o.order_date >= '2026-08-01'
AND o.order_date < '2026-09-01'
GROUP BY c.customer_id, c.customer_name
ORDER BY c.customer_id;
"""
REVISED_SQL = """
SELECT c.customer_id, c.customer_name, COALESCE(SUM(o.amount), 0)
FROM customers AS c
LEFT JOIN orders AS o
ON o.customer_id = c.customer_id
AND o.status = 'PAID'
AND o.order_date >= '2026-08-01'
AND o.order_date < '2026-09-01'
GROUP BY c.customer_id, c.customer_name
ORDER BY c.customer_id;
"""
EXPECTED = [
(1, "Ana", 100),
(2, "Ben", 25),
(3, "Cara", 0),
]
def run_query(connection, sql):
return connection.execute(sql).fetchall()
def main() -> None:
if not DATABASE.is_file():
raise FileNotFoundError(f"Database not found: {DATABASE}")
if OUTPUT_DIR.exists():
raise FileExistsError(f"Output folder already exists: {OUTPUT_DIR}")
connection = sqlite3.connect(f"file:{DATABASE.resolve()}?mode=ro", uri=True)
try:
ai_rows = run_query(connection, AI_SQL)
revised_rows = run_query(connection, REVISED_SQL)
finally:
connection.close()
OUTPUT_DIR.parent.mkdir(parents=True, exist_ok=True)
OUTPUT_DIR.mkdir()
with REPORT.open("x", encoding="utf-8", newline="") as stream:
writer = csv.writer(stream)
writer.writerow(["query", "rows", "matches_expected"])
writer.writerow(["AI", repr(ai_rows), ai_rows == EXPECTED])
writer.writerow(["REVISED", repr(revised_rows), revised_rows == EXPECTED])
print(f"Expected rows: {len(EXPECTED)}.")
print(f"AI rows: {len(ai_rows)}; matches expected: {ai_rows == EXPECTED}.")
print(
f"Revised rows: {len(revised_rows)}; "
f"matches expected: {revised_rows == EXPECTED}."
)
print(f"Report: {REPORT.as_posix()}")
if revised_rows != EXPECTED:
raise RuntimeError("Revised SQL does not match the expected result.")
if __name__ == "__main__":
main()
text
python ai_sql_check.py
06Comprueba la salida esperada
La consulta de IA debe devolver solo a Ana y Ben, por lo que produce 2 filas y no coincide con el resultado esperado. La consulta revisada debe devolver a los 3 clientes y coincidir exactamente con la tabla calculada a mano.
Consulta
Filas devueltas
Total general esperado
Coincide con la tabla esperada
IA
2
125
No
Revisada
3
125
Sí
El resultado de la IA puede seguir teniendo el total general correcto de 125 aunque sea incorrecto, porque falta la fila obligatoria de Cara con valor cero. Por eso no basta con comprobar solo los totales.
Comprueba el número de filas además de los totales.
Incluye en los datos sintéticos clientes con cero registros coincidentes cuando el requisito indique que deben aparecer.
Prueba límites de fecha como August 31 y September 1.
Incluye estados excluidos como CANCELLED.
Vuelve a ejecutar el comprobador sin cambiar OUTPUT_DIR. Debe detenerse con FileExistsError en lugar de sobrescribir el informe.
Problema común
Qué revisar
Faltan filas de forma inesperada
Comprueba el tipo de JOIN y si los filtros en WHERE eliminan filas no coincidentes de un LEFT JOIN.
Totales demasiado altos
Busca joins uno-a-muchos que dupliquen filas antes de la agregación.
Intervalo de fechas incorrecto
Usa un límite inferior explícito y un límite superior exclusivo adecuado al formato de fecha almacenado.
NULL en lugar de cero
Decide si las coincidencias ausentes deben quedarse como NULL o convertirse con COALESCE.
Total correcto pero detalle incorrecto
Compara todas las filas esperadas, no solo el total general.
Esta prueba solo demuestra que la consulta revisada coincide con este pequeño ejemplo sintético. Los esquemas reales pueden contener relaciones duplicadas, valores NULL, timestamps, time zones, refunds o reglas de negocio adicionales. Amplía los datos de prueba cuando esas condiciones sean importantes.
Registro de ejecución y verificación
ChatGPT Python tool · Python 3.13.5 · standard library csv/pathlib/sqlite3
Las filas esperadas calculadas manualmente se confirmaron como (1, Ana, 100), (2, Ben, 25) y (3, Cara, 0), con un total general de 125.
La consulta de IA devolvió exactamente 2 filas: Ana=100 y Ben=25. Cara se omitió, por lo que el resultado no coincidió con EXPECTED.
La consulta revisada con LEFT JOIN devolvió exactamente 3 filas: Ana=100, Ben=25 y Cara=0, coincidiendo exactamente con EXPECTED.
La ejecución principal imprimió exactamente: 'Expected rows: 3.', 'AI rows: 2; matches expected: False.', 'Revised rows: 3; matches expected: True.' y 'Report: outputs/ai_sql_check_result/sql_check.csv'.
sql_check.csv contenía un encabezado y dos filas de datos. La fila AI registró "[(1, 'Ana', 100), (2, 'Ben', 25)]" con False, y la fila REVISED registró "[(1, 'Ana', 100), (2, 'Ben', 25), (3, 'Cara', 0)]" con True.
El resultado de IA seguía sumando 125 a pesar de omitir a Cara, confirmando la afirmación del artículo de que el total general por sí solo no es suficiente.
El hash SHA-256 de orders.sqlite permaneció sin cambios después de ejecutar el comprobador, confirmando que la base de datos se abrió en modo de solo lectura y no se modificó.
Una segunda ejecución del comprobador se detuvo con FileExistsError porque outputs/ai_sql_check_result ya existía.
Límites de la verificación
No se realizaron pruebas de estrés específicas sobre valores amount NULL, relaciones de unión duplicadas, casos adicionales de límites de fechas como el 31 de agosto, marcas de tiempo, zonas horarias, reembolsos, bases de datos dañadas, fallos de permisos ni conjuntos de datos grandes.
El entorno de Python emitió en stderr una advertencia no relacionada del calentamiento de la herramienta de hojas de cálculo artifact-tool, pero ambos scripts del artículo se ejecutaron correctamente y el comprobador terminó con código 0 en la ejecución de verificación.
Fuentes de referencia
Las explicaciones y los ejemplos son de elaboración propia. Puedes consultar los comportamientos y conceptos relacionados en las siguientes fuentes oficiales.
Convierte “automatiza esto” en una descripción de tarea ejecutable. Adjunta una muestra sintética sin datos sensibles y un resultado esperado comprobado manualmente para completar una solicitud de script que totalice registros de trabajo por equipo.
Comprueba una función de agregación con cuatro filas que puedes calcular manualmente y 12 unit tests. Verifica no solo valores normales, sino también entrada vacía, cero, decimales y entrada no válida.
Compara un informe de IA con sus datos de origen, recalcula totales y porcentajes y usa una instrucción para detectar afirmaciones sin respaldo y causas exageradas antes de entregarlo.
Trata una expresión regular generada por IA como un borrador, no como una regla terminada. Crea una pequeña tabla de pruebas sintéticas, compara las coincidencias esperadas con las reales, corrige el patrón y guarda un informe de revisión antes de usarlo con datos reales.