SQL
Formatear consulta SQL online
Indentación consistente, cláusulas en su línea y resaltado de sintaxis, con el motor que uses. Lo que lo diferencia: aguanta consultas de verdad —CTE, funciones de ventana, subconsultas anidadas y procedimientos enteros con su lógica de control—, que es donde se rompen casi todos los formateadores en línea.
Tu consulta lleva el esquema de tu base de datos y a veces datos reales. Aquí no sale de la página.
Por qué esto no se sube, y por qué aquí importa más que en otras herramientas
Una consulta no es texto neutro. Lleva los nombres de tus tablas y columnas, que son el esquema de tu base de datos. Lleva la lógica de negocio escrita en el WHERE y en el CASE. Y muy a menudo lleva datos reales, porque la consulta que pegas es la que estabas depurando: con el identificador del cliente que dio el problema, el correo del usuario, el importe de la factura que no cuadra.
Un formateador que procesa en el servidor deja todo eso en el registro de alguien. No hace falta mala fe: basta un registro de acceso rotando durante noventa días. Y no hay ninguna razón técnica para ello: ordenar el espacio en blanco de un texto no necesita un servidor. Aquí el motor se descarga a tu navegador y trabaja dentro. Carga la página, desconecta internet y compruébalo.
Cómo funciona, en 3 pasos
-
Elige tu motor y pega
SQL Server, MySQL, PostgreSQL, Oracle o SQLite. Importa: cambian las comillas, los comentarios y la sintaxis de los procedimientos. El resultado sale mientras escribes.
-
Ajusta a tu estilo
Sangría de 2, 4 u 8 espacios o tabulador, palabras clave en mayúsculas o minúsculas, y comas al final de línea o al principio. Se queda recordado tu motor para la próxima.
-
Copia, minifica o parametriza
Cópialo, descárgalo como
.sql, aplástalo a una línea para meterlo en un registro, o cambia sus valores por parámetros y llévate la lista aparte.
Para qué la usa la gente
- Entender la consulta que heredasteDoscientas líneas en una sola, sin un salto. Formatearla es el primer paso para saber qué hace antes de tocarla.
- Dejarla presentable antes de la revisiónQue la diferencia del control de versiones enseñe el cambio de lógica y no un baile de espacios.
- Pasarla al códigoParametrizar la consulta que probaste a mano, con su lista de valores, y pegarla en el repositorio sin literales sueltos.
- Meterla en una líneaPara un registro, una variable de configuración o una celda de una hoja: minificar sin tocar lo que va dentro de las cadenas.
-
Ordenar un procedimientoCon su
BEGIN/END, sus condiciones y su control de errores indentados como es debido. - Encontrar el paréntesis que faltaCon la consulta indentada, un nivel descuadrado se ve a simple vista.
Dónde se rompen los formateadores en línea
Casi todos usan la misma biblioteca por debajo, y esa biblioteca hace muy bien las consultas: una expresión común de tabla con dos WITH, un par de funciones de ventana y un CASE de cuatro ramas sale impecable. El problema es el código procedimental. Pegas un procedimiento y lo que sale es esto:
CREATE PROCEDURE
dbo.ActualizarStock @producto_id int,
@cantidad int AS BEGIN
SET
NOCOUNT ON;
IF @stock IS NULL BEGIN RAISERROR ('no existe', 16, 1);
ROLLBACK TRANSACTION;
END
UPDATE productos
SET
stock = stock - @cantidad
CREATE PROCEDURE dbo.ActualizarStock @producto_id INT, @cantidad INT AS
BEGIN
SET NOCOUNT ON;
IF @stock IS NULL
BEGIN
RAISERROR ('no existe', 16, 1);
ROLLBACK TRANSACTION;
RETURN;
END
UPDATE productos
SET
stock = stock - @cantidad
La diferencia no es cosmética: en la columna de la izquierda no hay un solo nivel de indentación, así que no se ve qué va dentro del IF ni dónde acaba el bloque, que es exactamente lo que ibas a mirar.
Aquí el guion se trocea primero en bloques: lo que es una consulta se formatea con la biblioteca, y la estructura procedimental la indenta un motor propio. Eso obliga a resolver cuatro cosas que parecen tonterías y no lo son:
ENDno siempre cierra un bloque: el de unCASEtambién se escribe así, y si no se lleva la cuenta, la primera consulta con unCASEdentro de un procedimiento descuadra toda la indentación de ahí para abajo.BEGIN TRANSACTIONno abre un bloque;BEGINa secas, sí.IFseguido de paréntesis es la funciónIF()de MySQL, no un condicional.- En SQL Server no existe
END IF: ahí unENDseguido de unIFson dos cosas distintas —el cierre de un bloque y el principio de otra condición—, mientras que en Oracle y en PL/pgSQL sí forman una pieza. Confundirlos se come una condición entera.
Qué hace la parametrización, y por qué importa
Cuando pruebas algo en el editor de la base de datos escribes los valores a mano: where cliente_id = 42 and estado = 'pendiente'. Cuando eso pasa al código, los valores tienen que ir como parámetros, por dos razones que no tienen nada que ver entre sí: para que el motor reutilice el plan de ejecución en vez de compilar uno nuevo por cada valor distinto, y para no dejar la puerta abierta a una inyección de SQL.
El botón hace ese paso. Los nombres salen de la columna con la que se compara cada valor, así que la lista se lee sola: te salen :cliente_id y :estado, no :p1 y :p2. Puedes elegir entre los cuatro estilos habituales —:nombre, @nombre, $1 y ?— y llevarte la lista de valores como JSON o como texto.
Y hay números que se dejan en paz a propósito, porque no son valores: el 50 de varchar(50) es el tamaño del tipo; los de GROUP BY 1, 2 son posiciones de columna; y los de LIMIT o TOP se quedan porque muchos controladores no admiten un parámetro ahí y convertirlos te daría una consulta que falla al ejecutarse.
Por qué hay que elegir el motor
Porque cambia más de lo que parece, y no solo las funciones. Cambia cómo se cita un identificador: corchetes en SQL Server, acento grave en MySQL, comillas dobles en PostgreSQL y Oracle. Cambia qué significan las comillas dobles: en MySQL delimitan una cadena y en PostgreSQL un nombre de columna, así que el mismo texto se colorea y se formatea distinto. El comentario con almohadilla solo existe en MySQL. Y la sintaxis procedimental cambia entera, como se ha visto arriba con el END IF.
Buenas prácticas para que un SQL se lea
Formatear resuelve el espacio en blanco. Lo demás es cómo escribes, y son cuatro costumbres que se pillan en una tarde y ahorran mucho tiempo al de dentro de seis meses, que probablemente seas tú.
Las cuatro que más se notan
| Costumbre | Por qué |
|---|---|
| Una cosa por línea | Una columna por línea en el SELECT, una condición por línea en el WHERE, un JOIN por línea. Al añadir o quitar una, la diferencia del control de versiones señala esa línea y nada más. Es lo que hace esta herramienta por defecto. |
| Alias cortos pero con sentido | p para pedidos y c para clientes se sigue bien; a, b y t1 obligan a subir cada dos líneas a recordar qué era cada uno. Y califica siempre las columnas con su alias: sin eso, al añadir una columna a una tabla se puede volver ambigua una consulta que llevaba años funcionando. |
WITH antes que subconsultas anidadas |
Tres niveles de subconsulta se leen de dentro afuera, que es al revés de como se piensa. Partirlo en expresiones comunes de tabla con nombre las pone en el orden en el que ocurren y cada paso queda bautizado. |
Nunca SELECT * en producción |
Trae columnas que no usas, impide que el motor resuelva la consulta solo con el índice, y el día que alguien añade una columna a la tabla tu código recibe algo que no esperaba. Para mirar por encima está bien; para dejarlo escrito, no. |
Un ejemplo de lo mismo escrito de dos maneras
select * from pedidos p, clientes c
where p.cliente_id=c.id and p.total>(select
avg(total) from pedidos where estado='ok')
and c.pais='ES' and p.fecha>'2026-01-01'
WITH media AS (
SELECT AVG(total) AS importe
FROM pedidos
WHERE estado = 'ok'
)
SELECT p.id, p.fecha, p.total, c.nombre
FROM pedidos p
INNER JOIN clientes c ON c.id = p.cliente_id
CROSS JOIN media m
WHERE p.total > m.importe
AND c.pais = 'ES'
AND p.fecha > '2026-01-01'
La segunda versión no es solo más bonita: la unión está escrita con JOIN en vez de con comas en el FROM —así se ve cuál es la condición de unión y cuál es el filtro—, la subconsulta tiene nombre, y ya no se traen columnas que nadie usa.
Si lo que tienes es un CSV y quieres montar las sentencias de inserción, el sitio tiene un conversor de CSV a SQL que hace justo eso.
Preguntas frecuentes
¿Se sube mi consulta a algún servidor?
No, y aquí importa más que en casi cualquier otra herramienta. Una consulta lleva los nombres de tus tablas, la lógica del negocio en el WHERE, y muy a menudo datos reales: el identificador del cliente que dio el problema, el correo del usuario, el importe que no cuadra.
Un formateador que procesa en servidor deja todo eso en el registro de alguien, y no hay ninguna razón técnica para ello. Aquí el motor se descarga a tu navegador. Con la página ya cargada, desconecta internet y compruébalo.
¿Funciona con procedimientos, no solo con consultas?
Sí, y es la razón por la que existe. La biblioteca que usan casi todos los formateadores resuelve bien las consultas y mal el código procedimental: un procedimiento sale en una línea y sin indentar.
Aquí el guion se trocea en bloques primero: las consultas van a la biblioteca y la estructura —BEGIN/END, IF/ELSE, WHILE, TRY/CATCH— la indenta un motor propio que sabe que BEGIN TRANSACTION no abre bloque, que el END de un CASE no lo cierra, y que END IF existe en Oracle pero no en SQL Server.
¿Por qué hay que elegir el motor?
Porque cambian las comillas —corchetes en SQL Server, acento grave en MySQL, comillas dobles en PostgreSQL y Oracle—, cambia qué es una comilla doble (cadena en MySQL, identificador en PostgreSQL), y el comentario con almohadilla solo existe en MySQL.
Y cambia la sintaxis procedimental entera: el IF de SQL Server alcanza a una sentencia, y el de Oracle abre un bloque hasta END IF. Elegir mal no suele romper nada, pero produce detalles raros.
¿Qué hace el botón de parametrizar?
Cambia los valores literales por parámetros con nombre y te da la lista de valores aparte. Es el paso de llevar una consulta de una sesión de depuración al código: allí los valores van como parámetros para que el motor reutilice el plan de ejecución y para no dejar hueco a una inyección.
Los nombres salen de la columna con la que se compara cada valor, así que sale :cliente_id y no :p1. Hay cuatro estilos: :nombre, @nombre, $1 y ?.
¿Qué valores no se convierten en parámetros?
Los que no son valores aunque lo parezcan: el 50 de varchar(50) y el 10,2 de decimal(10,2) son el tamaño del tipo; los de GROUP BY 1, 2 y ORDER BY 2 son posiciones de columna y sustituirlos rompería la consulta.
Los de LIMIT, TOP, OFFSET y FETCH se dejan porque muchos controladores no admiten un parámetro ahí, y convertirlos te daría una consulta que falla al ejecutarse. Lo que hay dentro de un comentario tampoco se toca.
¿Cambia el formateo lo que hace la consulta?
No. Solo se toca el espacio en blanco y, si lo pides, las mayúsculas de las palabras clave. El contenido de las cadenas no se toca nunca: si dentro de una hay dos espacios seguidos siguen ahí, porque ahí un espacio es un dato.
Los comentarios se conservan al formatear y se quitan al minificar. Y el minificado no pega una palabra a una comilla aunque el motor lo aceptara: no ahorra nada que importe y hace el resultado ilegible.
¿Hay límite de tamaño?
Ninguno impuesto: el límite es la memoria de tu navegador y con un guion normal ni te acercas. Cuatrocientas sentencias se formatean en unas décimas de segundo.
Lo único que cambia por encima de unos doscientos mil caracteres es que deja de reformatearse a cada tecla y pasa a hacerlo al pulsar un botón, para que la página no se quede pensando mientras escribes. Se te avisa cuando pasa.
¿Y si mi consulta tiene un error de sintaxis?
Se formatea lo que se puede. Esto no valida ni comprueba que la consulta se ejecute: es un formateador, y su trabajo es ordenar el texto. Un trozo que no se sabe leer sale al menos con los espacios normalizados en lugar de desaparecer.
El único caso que se avisa expresamente es la comilla sin cerrar, porque a partir de ahí no se puede saber dónde acaba el texto y todo lo de después se interpreta mal. Es además lo que más pasa al pegar una consulta cortada por la mitad.