Aikido

Cómo evitar SELECT * en SQL: previniendo fugas de datos

Rendimiento

Regla
Evite SELECCIONE * en SQL consultas.
SELECT * en producción código hace que aplicaciones
frágiles a esquema cambios y oscurece datos dependencias.

Idiomas admitidos: 45+

Introducción

Uso SELECT * en las consultas de producción recupera todas las columnas de una tabla, incluidas las columnas que tu aplicación no utiliza. Cuando los esquemas de la base de datos evolucionan y se añaden nuevas columnas (incluyendo datos sensibles como contraseñas o PII), las consultas que utilizan SELECT * empieza a recuperarlos automáticamente sin cambios en el código. Esto crea vulnerabilidades de seguridad y rompe las suposiciones en la lógica de tu aplicación.

Por qué es importante

Impacto en el rendimiento: La recuperación de columnas innecesarias aumenta el tiempo de ejecución de las consultas, el tamaño de la transferencia de red y el consumo de memoria. Una tabla con 50 columnas de las que solo necesita 5 significa que está transfiriendo 10 veces más datos de lo necesario, lo que degrada los tiempos de respuesta y aumenta los costes de infraestructura.

Implicaciones de seguridad: Las nuevas columnas añadidas a las tablas (campos de auditoría, indicadores internos, datos sensibles de usuario) se exponen automáticamente a través de SELECT * consultas. Tu API podría empezar a filtrar hashes de contraseñas, números de la seguridad social o datos internos de negocio que nunca estuvieron destinados a ese endpoint.

Mantenibilidad del código: ¿Cuándo? SELECT * las consultas fallan tras cambios de esquema, el fallo ocurre en tiempo de ejecución, no en tiempo de compilación. Una nueva columna no nula o un campo renombrado provoca errores en producción. Las listas de columnas explícitas clarifican las dependencias y rompen las compilaciones cuando los esquemas cambian de forma incompatible.

Ejemplos de código

❌ No conforme:

async function getUserProfile(userId) {
    const query = 'SELECT * FROM users WHERE id = ?';
    const [user] = await db.execute(query, [userId]);

    return {
        name: user.name,
        email: user.email,
        createdAt: user.created_at
    };
}

Por qué está mal: Esto recupera todas las columnas, incluyendo campos potencialmente sensibles como password_hash, ssn, internal_notes o deleted_at. A medida que el esquema crece, esta consulta se vuelve más lenta y expone más datos, aunque la aplicación solo utiliza tres campos.

✅ Conforme:

async function getUserProfile(userId) {
    const query = `
        SELECT name, email, created_at
        FROM users
        WHERE id = ?
    `;
    const [user] = await db.execute(query, [userId]);

    return {
        name: user.name,
        email: user.email,
        createdAt: user.created_at
    };
}

Conclusión

Especifique siempre listas de columnas explícitas en las consultas SQL. Esto evita fugas de datos, mejora el rendimiento y clarifica las dependencias entre el código y el esquema. El pequeño coste inicial de escribir los nombres de las columnas previene clases enteras de problemas de seguridad y rendimiento.

Preguntas frecuentes

¿Tiene preguntas?

¿Cuándo es aceptable SELECT *?

Solo en consultas ad-hoc durante el desarrollo o la depuración, nunca en código de producción. Para scripts de migración de datos o informes puntuales donde realmente necesita todas las columnas, SELECT * es razonable. Para el código de aplicación, utilice siempre listas de columnas explícitas incluso si actualmente necesita todas las columnas, porque los cambios de esquema son inevitables.

¿Qué hay de los ORM que generan consultas SELECT *?

Configure your ORM to select specific fields. Most ORMs (Sequelize, TypeORM, Prisma, SQLAlchemy) support field selection: User.findOne({ attributes: ['name', 'email'] }) or prisma.user.findUnique({ select: { name: true, email: true } }). Always use these options to control what data is retrieved.

¿`SELECT *` impacta significativamente en el rendimiento de la base de datos?

Sí, especialmente con tablas anchas. Las bases de datos deben leer más páginas del disco, los índices no pueden utilizarse con la misma eficacia y los conjuntos de resultados de las consultas consumen más memoria en el pool de búfer de la base de datos. El tiempo de transferencia de red aumenta proporcionalmente al tamaño de los datos. Para tablas con columnas TEXT o BLOB, el impacto puede ser grave.

¿Cómo gestiono las consultas en las que necesito la mayoría de las columnas?

Enumérelos explícitamente. Utilice el autocompletado de su IDE o consulte el information_schema para generar la lista de columnas. Algunos equipos crean objetos de vista o utilizan vistas de base de datos que definen las columnas exactas necesarias para cada caso de uso. La claridad y seguridad de las listas explícitas superan la pequeña inconveniencia.

¿Cómo detecto SELECT * en mi base de código?

Busque el patrón SELECT * (sin distinción entre mayúsculas y minúsculas) en su base de código. Muchas herramientas de análisis estático y analizadores de consultas de bases de datos pueden marcarlos. Durante la revisión de código, rechace cualquier PR que contenga SELECT * en el código de la aplicación. Algunos equipos utilizan hooks de pre-commit o comprobaciones de CI para detectar y bloquear automáticamente estos patrones.

Asegúrate ahora.

Proteja su código, la nube y el entorno de ejecución en un único sistema central.
Encuentre y corrija vulnerabilidades de forma rápida y automática.

No se requiere tarjeta de crédito | Resultados del escaneo en 32 segundos.