Saltar al contenido
SDETRole
SDETRole

Aprender / Hoja de referencia

Hoja de referencia de SQL para testers

El SQL que usan los testers para verificar los datos detrás de una UI o una API: encontrar el registro, comprobar que cambió y buscar duplicados, huérfanos y NULL que no deberían estar ahí. La sintaxis es SQL estándar que funciona en PostgreSQL, MySQL 8 y SQLite. Cuando una base de datos se comporta distinto, la nota lo indica.

Revisada con SQL estándar; revisado con PostgreSQL 16, MySQL 8 y SQLite 3

Buscar filas

TareaCódigo
Columnas de una tabla SELECT id, email FROM users;
Filtrar SELECT * FROM orders WHERE status = 'paid' AND total > 100;
Uno de varios valores WHERE status IN ('paid', 'shipped')
Rango (ambos extremos incluidos) WHERE created_at BETWEEN '2026-01-01' AND '2026-01-31'
Patrón WHERE email LIKE '%@example.com'
Valor ausente WHERE phone IS NULL
Ordenar, más recientes primero ORDER BY created_at DESC
Primeras 10 filas LIMIT 10
Valores distintos SELECT DISTINCT status FROM orders;

SQL Server usa SELECT TOP 10 en lugar de LIMIT. BETWEEN sobre timestamps solo incluye la medianoche de la fecha final; usa < día siguiente para días completos.

Agregar

TareaCódigo
Contar filas SELECT COUNT(*) FROM orders;
Contar valores no NULL SELECT COUNT(shipped_at) FROM orders;
Contar valores distintos SELECT COUNT(DISTINCT user_id) FROM orders;
Totales por grupo SELECT status, COUNT(*), SUM(total) FROM orders GROUP BY status;
Filtrar grupos SELECT user_id, COUNT(*) FROM orders GROUP BY user_id HAVING COUNT(*) > 5;
Mínimo, máximo, media SELECT MIN(total), MAX(total), AVG(total) FROM orders;

WHERE filtra las filas antes de agrupar; HAVING filtra los grupos después.

Join

TareaCódigo
Solo las filas que coinciden SELECT o.id, u.email FROM orders o JOIN users u ON u.id = o.user_id;
Conservar todas las filas de la izquierda SELECT u.email, o.id FROM users u LEFT JOIN orders o ON o.user_id = u.id;
Filas sin coincidencia (anti-join) SELECT u.* FROM users u LEFT JOIN orders o ON o.user_id = u.id WHERE o.id IS NULL;
Lo mismo, con NOT EXISTS SELECT * FROM users u WHERE NOT EXISTS (SELECT 1 FROM orders o WHERE o.user_id = u.id);

Un join sobre una clave uno a muchos repite el lado "uno". Si SUM() parece demasiado grande después de un join, el join multiplicó las filas.

Comprobaciones de datos que hacen los testers

TareaCódigo
Duplicados SELECT email, COUNT(*) FROM users GROUP BY email HAVING COUNT(*) > 1;
Huérfanos (hijo sin padre) SELECT o.* FROM orders o LEFT JOIN users u ON u.id = o.user_id WHERE u.id IS NULL;
Campo obligatorio vacío SELECT * FROM users WHERE email IS NULL OR TRIM(email) = '';
Valores fuera de rango SELECT * FROM order_items WHERE quantity <= 0 OR unit_price < 0;
Total de cabecera ≠ líneas del pedido SELECT o.id FROM orders o JOIN order_items i ON i.order_id = o.id GROUP BY o.id, o.total HAVING o.total <> SUM(i.quantity * i.unit_price);
La fila existe tras una acción en la UI SELECT * FROM orders WHERE user_id = 42 ORDER BY created_at DESC LIMIT 1;

Trampas con NULL

TrampaQué ocurre
WHERE col = NULL Nunca es verdadero. Usa IS NULL / IS NOT NULL.
WHERE status <> 'paid' Omite las filas donde status es NULL. Añade OR status IS NULL si las quieres.
NOT IN (subconsulta que devuelve un NULL) No devuelve ninguna fila. Usa NOT EXISTS en su lugar.
COUNT(col) vs COUNT(*) COUNT(col) omite los NULL; COUNT(*) cuenta todas las filas.
Aritmética con NULL price + NULL es NULL. Envuélvelo con COALESCE(col, 0) si 0 es el valor por defecto correcto.

Funciones de ventana

TareaCódigo
Numerar filas por grupo ROW_NUMBER() OVER (PARTITION BY user_id ORDER BY created_at DESC)
Última fila de cada grupo SELECT * FROM (SELECT o.*, ROW_NUMBER() OVER (PARTITION BY user_id ORDER BY created_at DESC) AS rn FROM orders o) t WHERE rn = 1;
Ranking con empates RANK() OVER (ORDER BY total DESC) / DENSE_RANK() …
Valor de la fila anterior LAG(status) OVER (PARTITION BY test_name ORDER BY run_at)
Total acumulado SUM(total) OVER (ORDER BY created_at)

Compatibles con PostgreSQL, MySQL 8+, SQLite 3.25+ y SQL Server. Una función de ventana no se puede usar en WHERE; filtra en una consulta exterior.

Modificar datos con seguridad

TareaCódigo
Insertar INSERT INTO users (email, name) VALUES ('qa+1@example.com', 'QA One');
Actualizar (siempre con WHERE) UPDATE orders SET status = 'cancelled' WHERE id = 1043;
Borrar (siempre con WHERE) DELETE FROM sessions WHERE user_id = 42;
Probarlo y deshacerlo
BEGIN;
UPDATE orders SET status = 'cancelled' WHERE id = 1043;
SELECT status FROM orders WHERE id = 1043;
ROLLBACK;

Ejecuta primero el mismo WHERE como SELECT y comprueba el número de filas antes de hacer UPDATE o DELETE.

Practica y profundiza

Más hojas de referencia

Escribe para buscar en todo SDETRole.

Búsqueda de texto completo con Pagefind · se ejecuta en tu navegador Abrir la página de búsqueda →