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 archivos 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.
Se calculó manualmente el total válido de Ana en agosto como 40 + 60 = 100.
Se calculó manualmente el total válido de Ben en agosto como 25 y se excluyó su pedido de septiembre.
Se determinó manualmente que Cara debe aparecer con 0 porque su único pedido de agosto es CANCELLED.
Se calculó manualmente el total general esperado como 125 y el número esperado de filas como 3.
Se revisó la consulta de IA y se determinó que su INNER JOIN y sus filtros WHERE omiten a Cara, produciendo 2 filas.
Se revisó la consulta LEFT JOIN corregida y se esperaba que devolviera las tres filas calculadas a mano.
Se obtuvieron manualmente la salida de consola esperada y la comparación del informe.
Límites de la verificación
El autor de esta respuesta no ejecutó el código; el comportamiento de SQLite y del sistema de archivos no se probó aquí.
Solo se evaluaron las filas sintéticas indicadas; no se probaron importes NULL, joins duplicados, timestamps, time zones, refunds ni conjuntos de datos grandes.
Coincidir con este ejemplo no demuestra que la consulta sea correcta para todos los esquemas de producción o reglas de negocio.
Las URL de la documentación oficial se proporcionaron desde ubicaciones conocidas, pero no se comprobaron en tiempo real.
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.
Divide un resumen plausible en hechos, cálculos e interpretaciones. Recalcula proporciones y promedios a partir de datos mensuales sintéticos y reescribe las frases con fuentes faltantes o causas exageradas para convertirlas en afirmaciones comprobables.
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.