Buenas prácticas de indentación de declaración SQL
coding-style indentation (25)
¿Cuál es la práctica aceptada para sangrar sentencias de SQL? Por ejemplo, considere la siguiente declaración SQL:
SELECT column1, column2
FROM table1
WHERE column3 IN
(
SELECT TOP(1) column4
FROM table2
INNER JOIN table3
ON table2.column1 = table3.column1
)
¿Cómo debe ser sangrado? Muchas gracias.
Acabo de ponerlo a través de mi prettifier SQL y salió así ...
SELECT column1, column2
FROM table1
WHERE column3 IN
(
SELECT TOP(1) column4
FROM table2
INNER JOIN table3
ON table2.column1 = table3.column1
)
http://extras.sqlservercentral.com/prettifier/prettifier.aspx
..... Pero no he encontrado la forma de poner los colores en .
Aquí está mi poke en esto:
select column1, column2
from table1
where (column3 in (
select top(1) column4
from table2
inner join table3
on (table2.column1 = table3.column1)
))
;
- Todo en minúsculas porque es más fácil leer caracteres en minúsculas (y tenemos resaltado de código para enfatizar las palabras clave) también es más fácil escribir
- Cada restricción u opción en una palabra clave (como la de en la selección o el en la unión) se sangra para mostrar su dependencia de la palabra clave externa
- El corchete de cierre tiene el mismo nivel de mellado que la abertura donde
- Use corchetes para las cláusulas where y on para aumentar la legibilidad
- Haga que el punto y coma cierre el enunciado de selección con el mismo sangrado, de modo que se puedan distinguir mejor los enunciados múltiples (si necesita un punto y coma en su idioma, como SAS PROC SQL)
- Todavía es bastante compacto y no se extiende por toda la página
Así es como lo haríamos aquí:
select COLUMN1, COLUMN2, case when COLUMN5 = ''X'' and COLUMN6 = ''Y'' then ''one'' when COLUMN5 in ( ''AAA'', ''BBB'' ) then ''two'' else ''three'' end as COLUMN7 from TABLE1 where COLUMN2 in ( select top(1) COLUMN4 from TABLE2 inner join TABLE3 on TABLE2.COLUMN1 = TABLE3.COLUMN1 and TABLE2.COLUMN2 between TABLE3.COLUMN2 and TABLE3.COLUMN3 )
Nuestra idea es: mantener las palabras clave sql en minúsculas y poner todas las cosas cambiantes (y por lo tanto "más interesantes") como nombres de tablas o columnas en mayúsculas. El código puede parecer un poco "explotado" aquí, pero aumenta la legibilidad si tiene consultas complejas con nombres más largos (incluido el esquema, etc.) mucho más que en este ejemplo. Y: sangra todos los objetos según su "nivel".
Bueno, por supuesto depende de la consulta.
Para consultas simples, un esquema de sangría altamente formal es más un problema de lo que vale y puede hacer que el código sea menos legible, no más. Pero a medida que la complejidad crece, debe comenzar a ser más cuidadoso con la estructura de la declaración, para asegurarse de que será legible nuevamente más adelante.
Como la mayoría de los anteriores han alineado los nombres de las columnas de retorno, encuentro que alinear nombres y condiciones de tablas ayuda mucho a la legibilidad.
SELECT
column1,
column2
FROM
table1
WHERE
column3 IN
(
SELECT TOP(1)
column4
FROM
table2 INNER JOIN
table3 ON table2.column1 = table3.column1
)
Y para cuando las condiciones de unión se alarguen.
SELECT
Column1,
Column2
FROM
Table1 JOIN
Table2 ON
Table1.Column3 = Table2.Column4 JOIN
Table3 ON
Table2.Column1 = Table3.Column1 and
Table2.ColumnX = @x and
Table3.ColumnY = @y
WHERE
Condition1=xxx and
Condition2=yyy and
(
Condition3=aaa or
Condition4=bbb
)
Ejemplo de sangrado de un SQL muy, muy complejo:
SELECT
produtos_cesta.cod_produtos_cesta,
produtos.nome_pequeno,
tab_contagem.cont,
produtos_cesta.sku,
produtos_kits.sku_r AS sku_kit,
sku_final = CASE
WHEN produtos_kits.sku_r IS NOT NULL THEN produtos_kits.sku_r
ELSE produtos_cesta.sku
END,
estoque = CASE
WHEN produtos2.estoque IS NOT NULL THEN produtos2.estoque
ELSE produtos.estoque
END,
produtos_cesta.unidades as unidades1,
unidades_x_quantidade = CASE
WHEN produtos.cod_produtos_kits_tipo = 1 THEN CAST(produtos_cesta.quantidade * (produtos_cesta.unidades / tab_contagem.cont) * produtos_kits.quantidade AS int)
ELSE CAST(produtos_cesta.quantidade * produtos_cesta.unidades AS int)
END,
unidades = CASE
WHEN produtos.cod_produtos_kits_tipo = 1 THEN produtos_cesta.unidades / tab_contagem.cont * produtos_kits.quantidade
ELSE produtos_cesta.unidades
END,
unidades_parent = produtos_cesta.unidades,
produtos_cesta.quantidade,
produtos.controla_estoque,
produtos.status
FROM
produtos_cesta
INNER JOIN produtos
ON (produtos_cesta.sku = produtos.sku)
INNER JOIN produtos_pacotes
ON (produtos_cesta.sku = produtos_pacotes.sku)
INNER JOIN (
SELECT
produtos_cesta.cod_produtos_cesta,
cont = SUM(
CASE
WHEN produtos_kits.quantidade IS NOT NULL THEN produtos_kits.quantidade
ELSE 1
END
)
FROM
produtos_cesta
LEFT JOIN produtos_kits
ON (produtos_cesta.sku = produtos_kits.sku)
LEFT JOIN produtos
ON (produtos_cesta.sku = produtos.sku)
WHERE
shopper_id = ''" + mscsShopperId + @"''
GROUP BY
produtos_cesta.cod_produtos_cesta,
produtos_cesta.sku,
produtos_cesta.unidades
)
AS tab_contagem
ON (produtos_cesta.cod_produtos_cesta = tab_contagem.cod_produtos_cesta)
LEFT JOIN produtos_kits
ON (produtos.sku = produtos_kits.sku)
LEFT JOIN produtos as produtos2
ON (produtos_kits.sku_r = produtos2.sku)
WHERE
shopper_id = ''" + mscsShopperId + @"''
GROUP BY
produtos_cesta.cod_produtos_cesta,
tab_contagem.cont,
produtos_cesta.sku,
produtos_kits.sku_r,
produtos.cod_produtos_kits_tipo,
produtos2.estoque,
produtos.controla_estoque,
produtos.estoque,
produtos.status,
produtos.nome_pequeno,
produtos_cesta.unidades,
produtos_cesta.quantidade,
produtos_kits.quantidade
ORDER BY
produtos_cesta.sku,
produtos_cesta.unidades DESC
El formateo de SQL es un área donde hay una gran cantidad de desacuerdos ... Pero me gusta enfocarme en la legibilidad y pensar que sea lo que sea que hagas, cumplir con las reglas que reducen la legibilidad es, como dice el viejo cliché, una "consistencia insensata" ("Consistencia absurda es un duende para las mentes simples")
Entonces, en lugar de llamarlos reglas, aquí hay algunas pautas. Para cada cláusula importante en una declaración SQL (Seleccionar, Insertar, Eliminar, De, Dónde, Tener, Agrupar POR, Ordenar Por, ... Me pueden faltar algunas) debe ser FÁCILMENTE identificable. Así que generalmente los guiones al más alto nivel, todos incluso entre ellos. Luego, dentro de cada cláusula, sangro la siguiente subestructura lógica de manera uniforme ... y así sucesivamente ... Pero me siento libre de (y a menudo lo hago) cambiar el patrón si en algún caso individual sería más fácil hacerlo ... Las declaraciones complejas de Case son un buen ejemplo. Como cualquier cosa que requiera desplazamiento horizontal reduce enormemente la legibilidad, a menudo escribo expresiones complejas (anidadas) en varias líneas. Cuando lo hago, trato de mantener el comienzo de dicha instrucción colgando sangría en función de su lugar lógico en la declaración SQL, y sangro el resto de las líneas de declaración de algunos caracteres furthur ...
El código de la base de datos SQL ha existido durante mucho tiempo, ya que antes las computadoras tenían minúsculas, por lo que existe una preferencia histórica por las palabras clave de mayúsculas, pero prefiero la legibilidad a la tradición ... (y cada herramienta que uso códigos de color las palabras clave ahora de todas formas)
También utilizaría alias de tabla para reducir la cantidad de texto que el ojo tiene que escanear para asimilar la estructura de la consulta, siempre que los alias no creen confusión. En una consulta con menos de 3 o 4 tablas, los alias de caracteres únicos están bien, a menudo uso la primera letra de la tabla si todas las tablas comienzan con una letra diferente ... nuevamente, lo que sea que más contribuya a la legibilidad. Finalmente, si su base de datos lo admite, muchas de las palabras clave son opcionales (como "Interno", "Externo", "Como" para alias, etc.) "Into" (de Insert Into) es opcional en el servidor Sql, pero no en Oracle). Tenga cuidado al usar esto si su código necesita ser independiente de la plataforma ...
Tu ejemplo, escribiría como:
Select column1, column2
From table1 T1
Where column3 In (Select Top(1) column4
From table2 T2
Join table3 T3
On T2.column1 = T3.column1)
O
Select column1, column2
From table1 T1
Where column3 In
(Select Top(1) column4
From table2 T2
Join table3 T3
On T2.column1 = T3.column1)
Si hay muchas más columnas en la cláusula select, doblaría la segunda línea y las posteriores ... En general, NO me atengo a ninguna regla estricta (una columna por fila) ya que el desplazamiento es casi tan malo para la legibilidad como el desplazamiento horizontal es, especialmente si solo las primeras diez columnas de la pantalla tienen texto en ellas)
Select column1, column2, Col3, Col4, column5,
column6, Column7, isNull(Column8, ''FedEx'') Shipper,
Case Upper(Column9)
When ''EAST'' Then ''JFK''
When ''SOUTH'' Then ''ATL''
When ''WEST'' Then ''LAX''
When ''NORTH'' Then ''CHI'' End HubPoint
From table1 T1
Where column3 In
(Select Top(1) column4
From table2 T2
Join table3 T3
On T2.column1 = T3.column1)
Formatee el código de la manera que sea más legible ...
Esta es mi preferencia normal:
....SELECT column1
........,column2
....FROM table1
....WHERE column3 IN (
........SELECT TOP(1) column4
........FROM table2
........INNER JOIN table3
............ON table2.column1 = table3.column1
....)
Aunque el confunde el formateo con un espacio extra, así que pongo algunos períodos para que pueda ver el formato real ...
Esta es una cuestión de gusto.
Esta es mi preferencia.
SELECT
column1
,column2
FROM
table1
WHERE column3 IN (
SELECT TOP(1) column4
FROM
table2
INNER JOIN table3
ON table2.column1 = table3.column1
)
Este enlace es el mejor que encontré. http://www.sqlinform.com/free_online_sw.html
Este es mi método personal. Dependiendo de la duración de la condición de unión, a veces la sangro en la línea de abajo.
SELECT
column1,
column2
FROM
table1
WHERE
column3 IN (
SELECT TOP(1)
column4
FROM
table2
INNER JOIN table3 ON table2.column1 = table3.column1
)
SELECT
column1,
column2
FROM
table1
WHERE
column3 IN (
SELECT TOP(1)
column4
FROM
table2
INNER JOIN table3
ON table2.column1 = table3.column1 -- for long ones
)
Formatearía así:
SELECT
column1,
column2
FROM
table1
WHERE
column3 IN (SELECT TOP(1)
column4
FROM
table2
INNER JOIN table3 ON table2.column1 = table3.column1)
o así:
SELECT
column1,
column2
FROM
table1
WHERE
column3 IN (SELECT TOP(1) column4
FROM table2
INNER JOIN table3 ON table2.column1 = table3.column1)
He escrito un estándar de código para nuestra tienda que está sesgado en extremo hacia la legibilidad / "descubrimiento" (este último es principalmente útil en las instrucciones de inserción-selección):
SELECT
column1,
column2
FROM
table1
WHERE
column3 IN
(
SELECT TOP(1)
column4
FROM
table2
INNER JOIN table3 ON table2.column1 = table3.column1
)
En consultas más complejas se vuelve más obvio cómo esto es útil:
SELECT
Column1,
Column2,
Function1
(
Column1,
Column2
) as Function1,
CASE
WHEN Column1 = 1 THEN
a
ELSE
B
END as Case1
FROM
Table1 t1
INNER JOIN Table2 t2 ON t1.column12 = t2.column21
WHERE
(
FilterClause1
AND FilterClause2
)
OR
(
FilterClause3
AND FilterClause4
)
Una vez que te mueves a sistemas con más de una sola combinación en la mayoría de tus consultas, mi experiencia me dice que usar el espacio vertical liberalmente es tu mejor amigo con SQL complejo.
Lo que suelo hacer es
print("SELECT column1, column2
FROM table1
WHERE column3 IN (SELECT TOP(1) column4
FROM table2 INNER JOIN
table3 ON table2.column1 = table3.column1)");
Me gusta la forma de jalbert de alinear las palabras clave a su derecha. También agregaría que me gustan los AND y los quirófanos de la izquierda (algunas personas los ponen a la derecha). Además, me gusta alinear mis signos iguales siempre que sea posible.
SELECT column1,
column2
FROM table1, table2
WHERE table1.column1 = table2.column4
AND table1.col5 = "hi"
OR table2.myfield = 678
Me gusta que las diferentes partes de mi consulta se alineen verticalmente. Tiendo a usar un tamaño de tabulación de 8 espacios para SQL que parece funcionar bien.
SELECT column1,
column2
FROM table1
WHERE column3 IN
(
SELECT TOP(1) column4
FROM table2
INNER JOIN table3
ON table2.column1 = table3.column1
)
Me gusta tener "ríos" de espacios en blanco en el código. Hace que sea un poco más fácil de escanear.
SELECT column1,
column2
FROM table1
WHERE column3 IN (SELECT column4
FROM table2
JOIN table3
ON table2.column1 = table3.column1);
No estoy seguro de que haya una práctica aceptada, pero ahora cómo lo haría:
SELECT
column1,
column2
FROM
table1
WHERE
column3 IN
(
SELECT TOP(1)
column4
FROM
table2
INNER JOIN
table3
ON table2.column1 = table3.column1
)
No sé si hay un estándar, pero me gusta hacerlo de esta manera;
SELECT column1, column2
FROM table1
WHERE column3 IN
(
SELECT TOP(1) column4
FROM table2
INNER JOIN table3
ON table2.column1 = table3.column1
)
porque puedo leer y analizar el SQL mejor.
Por supuesto, esto se reduce a las preferencias personales. Y si se trata de un equipo, es algo que debería acordarse entre los miembros por motivos de coherencia. Pero esta sería mi preferencia:
SELECT column1, column2
FROM table1
WHERE column3 IN(SELECT TOP(1) column4
FROM table2
INNER JOIN table3 ON
table2.column1 = table3.column1
)
Sí, esto es bastante subjetivo ... Pero aquí están mis 2 centavos:
SELECT
Column1,
Column2
FROM Table1
WHERE
Column3 IN (
SELECT Column4
FROM Table2
JOIN Table3 ON
Table2.Column1 = Table3.Column1
)
Pero, en realidad, probablemente lo reescribiera sin el IN:
SELECT
Column1,
Column2
FROM Table1
JOIN Table2 ON
Table1.Column3 = Table2.Column4
JOIN Table3 ON
Table2.Column1 = Table3.Column1
Básicamente, mis reglas son:
- Capitalizar palabras clave
- Las columnas van en líneas individuales, pero los modificadores SELECT (SELECT TOP 100, SELECT DISTINCT, etc.) o las columnas individuales (SELECT 1, SELECT Id, SELECT *, etc.) van en la misma línea
- Unir condiciones sangrado debajo cláusula JOIN
- Use JOIN para INNER JOIN (ya que es el más común), y especifique completamente otros (LEFT OUTER JOIN, FULL OUTER JOIN, etc.)
- Abra parens en la misma línea, cierre la página en una línea separada. Si tiene un alias, el alias va con paren cercano.
Si tiene una larga declaración de SQL que le gustaría volver a formatear sin todo el tipeo y tabulación, puede golpearlo en este sitio web y obtener un resultado muy formateado. Puede experimentar con varios formatos para ver cuál hace que su texto sea más legible.
Editar: creo que this es la ubicación 2014 del formateador SQL.
SELECT
Column1,
Column2
FROM
Table1
WHERE
Column3 IN
(
SELECT TOP (1)
Column4
FROM
Table2
INNER JOIN
Table3
ON
Table2.Column1 = Table3.Column1
)
SELECT column1
, column2
FROM table1
WHERE column3 IN
(
SELECT TOP(1) column4
FROM table2
INNER JOIN table3
ON table2.column1 = table3.column1
)
Me gusta tener todo "," al frente , así nunca los busco cuando hay un error en la línea X del editor de SQL.
Este es un ejemplo para aquellos que no usan este tipo de instrucción SQL de escritura. Ambos contienen un error de una coma faltante.
SELECT sdcolumn123
, dscolumn234
, sdcolumn343
, ffcolumn434
, sdcolumn543
, bvcolumn645
vccolumn754
, cccolumn834
, vvcolumn954
, cvcolumn104
FROM table1
WHERE column3 IN
(
...
)
SELECT sdcolumn123, dscolumn234, asdcolumn345, dscolumn456, ascolumn554, gfcolumn645 sdcolumn754, fdcolumn845, sdcolumn954, fdcolumn1054
FROM table1
WHERE column3 IN
(
...
)
Encontré más fácil y más rápido en el primer ejemplo. Espero que este ejemplo te muestre más mi punto de vista.
SELECT column1, column2
FROM table
WHERE column3 IN (
SELECT TOP(1) column4
FROM table2
INNER JOIN table3 ON table2.column1 = table3.column1
)
Esto es bastante corto y fácil de leer. Haría ajustes si hubiera más columnas seleccionadas o más condiciones de unión.