Estándares de formato SQL


En mi último trabajo, trabajamos en una aplicación muy pesada en bases de datos, y desarrollé algunos estándares de formato para que todos escribiéramos SQL con un diseño común. También desarrollamos estándares de codificación, pero estos son más específicos de la plataforma, así que no voy a entrar en ellos aquí.

Estoy interesado en saber qué usan otras personas para los estándares de formato SQL. A diferencia de la mayoría de los otros entornos de codificación, no he encontrado mucho consenso en línea para ellos.

Para cubrir la consulta principal tipos:

select
    ST.ColumnName1,
    JT.ColumnName2,
    SJT.ColumnName3
from 
    SourceTable ST
inner join JoinTable JT
    on JT.SourceTableID = ST.SourceTableID
inner join SecondJoinTable SJT
    on ST.SourceTableID = SJT.SourceTableID
    and JT.Column3 = SJT.Column4
where
    ST.SourceTableID = X
    and JT.ColumnName3 = Y

Hubo cierto desacuerdo sobre los feeds de línea después select, from y where. La intención en la línea select es permitir que otros operadores como" top X " sin alterar el diseño. Después de eso, simplemente mantener una línea de alimentación consistente después de los elementos clave de la consulta parecía dar como resultado un buen nivel de legibilidad.

Dejar caer el salto de línea después de from y where sería una revisión comprensible. Sin embargo, en consultas como el update a continuación, vemos que la línea de alimentación después de la where nos da una buena alineación de la columna. Del mismo modo, un salto de línea después de group by o order by mantiene nuestros diseños de columna claros y fáciles de leer.

update
    TargetTable
set
    ColumnName1 = @value,
    ColumnName2 = @value2
where
    Condition1 = @test

Finalmente, un insert:

insert into TargetTable (
    ColumnName1,
    ColumnName2,
    ColumnName3
) values (
    @value1,
    @value2,
    @value3
)

En su mayor parte, estos no se desvían tan lejos de la forma en que MS SQL Server Managements Studio / query analyser escriben SQL, sin embargo, lo hacen difieren.

Espero ver si hay algún consenso en la comunidad Stack Overflow sobre este tema. Estoy constantemente sorprendido de cuántos desarrolladores pueden seguir el formato estándar para otros idiomas y de repente ir tan al azar al golpear SQL.

Author: Sae1962, 2009-02-06

27 answers

Soy de la opinión de que siempre y cuando pueda leer el código fuente fácilmente, el formato es secundario. Siempre que se logre este objetivo, hay una serie de buenos estilos de diseño que se pueden adoptar.

El único otro aspecto que es importante para mí es que sea cual sea el diseño/estilo de codificación que elija adoptar en su tienda, asegúrese de que todos los codificadores lo utilicen de manera consistente.

Solo para su referencia, aquí es cómo presentaría el ejemplo que proporcionó, solo mi diseño preferencia. En particular, la cláusula ON está en la misma línea que la join, solo la condición de unión primaria se muestra en la unión (es decir, la coincidencia de clave) y otras condiciones se mueven a la cláusula where.

select
    ST.ColumnName1,
    JT.ColumnName2,
    SJT.ColumnName3
from 
    SourceTable ST
inner join JoinTable JT on 
    JT.SourceTableID = ST.SourceTableID
inner join SecondJoinTable SJT on 
    ST.SourceTableID = SJT.SourceTableID
where
        ST.SourceTableID = X
    and JT.ColumnName3 = Y
    and JT.Column3 = SJT.Column4

Un consejo, obtenga una copia de SQL Prompt de Red Gate. Puede personalizar la herramienta para usar sus preferencias de diseño deseadas, y luego los programadores de su tienda pueden usarla para garantizar que todos adopten los mismos estándares de codificación.

 16
Author: John Sansom,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-07-18 14:24:11

Respuesta tardía, pero con suerte útil.

Mi experiencia trabajando como parte del equipo de desarrollo más grande es que puede seguir adelante y definir cualquier estándar que desee, pero el problema es en realidad hacer cumplir estos o hacer que sea muy fácil para los desarrolladores implementar.

Como desarrolladores a veces creamos algo que funciona y luego decimos "Lo formatearé más tarde", pero eso más tarde nunca llega.

Inicialmente, usamos SQL Prompt (fue genial) para esto, pero luego cambiamos a ApexSQL Refactor, porque es una herramienta gratuita.

 22
Author: John Emeres,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-07-19 16:06:32

Llego tarde a la fiesta, pero solo agregaré mi estilo de formato preferido, que debo haber aprendido de libros y manuales: es compacto. Aquí está la declaración de ejemplo SELECT:

SELECT  st.column_name_1, jt.column_name_2,
        sjt.column_name_3
FROM    source_table AS st
        INNER JOIN join_table AS jt USING (source_table_id)
        INNER JOIN second_join_table AS sjt ON st.source_table_id = sjt.source_table_id
                AND jt.column_3 = sjt.column_4
WHERE   st.source_table_id = X
AND     jt.column_name_3 = Y

En resumen: sangría de 8 espacios, palabras clave en mayúsculas (aunque así las colorea mejor cuando están en minúsculas), sin camelcase (sin sentido en Oracle), y envolturas de línea cuando sea necesario.

El UPDATE:

UPDATE  target_table
SET     column_name_1 = @value,
        column_name_2 = @value2
WHERE   condition_1 = @test

Y el INSERT:

INSERT  INTO target_table (column_name_1, column_name_2,
                column_name_3)
VALUES  (@value1, @value2, @value3)

Ahora, permítanme ser el primero en admitir que este estilo tiene son problemas. La sangría de 8 espacios significa que ORDER BY y GROUP BY desalinean la sangría, o dividen la palabra BY por sí misma. También sería más natural indentar todo el predicado de la cláusula WHERE, pero generalmente alineo los operadores AND y OR en el margen izquierdo. Sangrar después de las líneas envueltas INNER JOIN también es algo arbitrario.

Pero por cualquier razón, todavía lo encuentro más fácil de leer que las alternativas.

Terminaré con uno de mis más complejos creaciones de los últimos tiempos utilizando este estilo de formato. Casi todo lo que encontrarías en una instrucción SELECT aparece en esta. (También ha sido alterado para disfrazar sus orígenes, y puede que haya introducido errores al hacerlo.)

SELECT  term, student_id,
        CASE
            WHEN ((ft_credits > 0 AND credits >= ft_credits) OR (ft_hours_per_week > 3 AND hours_per_week >= ft_hours_per_week)) THEN 'F'
            ELSE 'P'
        END AS status
FROM    (
        SELECT  term, student_id,
                pm.credits AS ft_credits, pm.hours AS ft_hours_per_week,
                SUM(credits) AS credits, SUM(hours_per_week) AS hours_per_week
        FROM    (
                SELECT  e.term, e.student_id, NVL(o.credits, 0) credits,
                        CASE
                            WHEN NVL(o.weeks, 0) > 5 THEN (NVL(o.lect_hours, 0) + NVL(o.lab_hours, 0) + NVL(o.ext_hours, 0)) / NVL(o.weeks, 0)
                            ELSE 0
                        END AS hours_per_week
                FROM    enrollment AS e
                        INNER JOIN offering AS o USING (term, offering_id)
                        INNER JOIN program_enrollment AS pe ON e.student_id = pe.student_id AND e.term = pe.term AND e.offering_id = pe.offering_id
                WHERE   e.registration_code NOT IN ('A7', 'D0', 'WL')
                )
                INNER JOIN student_history AS sh USING (student_id)
                INNER JOIN program_major AS pm ON sh.major_code_1 = pm._major_code AND sh.division_code_1 = pm.division_code
        WHERE   sh.eff_term = (
                        SELECT  MAX(eff_term)
                        FROM    student_history AS shi
                        WHERE   sh.student_id = shi.student_id
                        AND     shi.eff_term <= term)
        GROUP   BY term, student_id, pm.credits, pm.hours
        )
ORDER   BY term, student_id

Esta abominación calcula si un estudiante es a tiempo completo o a tiempo parcial en un término dado. Sin importar el estilo, este es difícil de leer.

 16
Author: yukondude,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-03-21 17:34:12

Agradable. Como programador de Python, estas son mis preferencias:

Nuevas líneas después select, from y where solo cuando es necesario para la legibilidad.

Cuando el código puede ser más compacto e igualmente legible, generalmente prefiero la forma más compacta. Ser capaz de encajar más código en una pantalla mejora la productividad.

select ST.ColumnName1, JT.ColumnName2, SJT.ColumnName3
from SourceTable ST
inner join JoinTable JT
    on JT.SourceTableID = ST.SourceTableID
inner join SecondJoinTable SJT
    on ST.SourceTableID = SJT.SourceTableID
    and JT.Column3 = SJT.Column4
where ST.SourceTableID = X and JT.ColumnName3 = Y

En última instancia, esto será una llamada de juicio que se hará durante la revisión del código.

Para insert, colocaría el paréntesis diferente:

insert into TargetTable (
    ColumnName1,
    ColumnName2,
    ColumnName3)
values (
    @value1,
    @value2,
    @value3)

El razonamiento para este formato es que si SQL utiliza sangría para la estructura de bloques (como Python), el paréntesis no sería necesario. Por lo tanto, si la sangría se utiliza de todos modos, entonces el paréntesis debe tener el efecto mínimo en el diseño. Esto se logra colocándolos al final de las líneas.

 4
Author: ddaa,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-07-19 09:03:02
SELECT
    a.col1                  AS [Column1]
    ,b.col2                 AS [Column2]
    ,c.col1                 AS [Column3]
FROM
    Table1 a
    INNER JOIN Table2 b     ON b.Id = a.bId
    INNER JOIN Table3 c     ON c.Id = a.cId
WHERE
    a.col     = X
    AND b.col = Y

Utiliza muchas más líneas que muchos de los ejemplos aquí, pero creo que es mucho más fácil de entender, permite la eliminación rápida de columnas/cláusulas/tablas. Ayuda a aprovechar un monitor orientado verticalmente.

 3
Author: RossBille,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-07-19 14:51:20

Yo sugeriría el siguiente estilo, basado en la sugerencia de Juan:

/*
<Query title>
<Describe the overall intent of the query>
<Development notes, or things to consider when using/interpreting the query>
*/
select
    ST.ColumnName1,
    JT.ColumnName2,
    SJT.ColumnName3
from 

    -- <Comment why this table is used, and why it's first in the list of joins>
    SourceTable ST

    -- <Comment why this join is made, and why it's an inner join>
    inner join JoinTable JT
        on ST.SourceTableID = JT.SourceTableID

    -- <Comment why this join is made, and why it's an left join>
    left join SecondJoinTable SJT
        on  ST.SourceTableID = SJT.SourceTableID
        and JT.Column3 = SJT.Column4

where

    -- comment why this filter is applied
    ST.SourceTableID = X

    -- comment why this filter is applied
    and JT.ColumnName3 = (
            select 
                somecolumn
            from 
                sometable
        )
;

Ventajas:
- Los comentarios son una parte esencial para hacer que el código sea legible y detectar errores.
- Agregar filtros-all - " on " a la unión evita errores al cambiar de unión interna a izquierda.
- Colocar el punto y coma en una nueva línea permite agregar/comentar fácilmente las cláusulas where.

 2
Author: Wouter,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-01-20 13:02:31

Tarde, pero voy a tirar mi sombrero en el ring. Se tarda un poco más en escribir, pero encuentro que surgen patrones con la alineación vertical que lo hacen muy legible una vez que estás acostumbrado.

SELECT ST.ColumnName1,
       JT.ColumnName2,
       SJT.ColumnName3,
       CASE WHEN condition1 = True 
             AND condition2 = True Then DoSomething
            Else DoSomethingElse
        END ColumnName4
  FROM SourceTable AS ST
 INNER
  JOIN JoinTable AS JT
    ON JT.SourceTableID = ST.SourceTableID
 INNER
  JOIN SecondJoinTable AS SJT
    ON ST.SourceTableID = SJT.SourceTableID
   AND JT.Column3 = SJT.Column4
  LEFT
  JOIN (SELECT Column5
          FROM Table4
       QUALIFY row_number() OVER
                 ( PARTITION BY pField1,
                                pField2
                       ORDER BY oField1
                 ) = 1
       ) AS subQry
    ON SJT.Column5 = subQry.Column5
 WHERE ST.SourceTableID = X
   AND JT.ColumnName3 = Y
 2
Author: Error_2646,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-07-26 20:01:35

Utilizo un formato similar al tuyo excepto que pongo la palabra clave ON en la misma línea que la combinación y pongo los operadores AND y OR al final de las líneas para que todos mis criterios de combinación/selección se alineen bien.

Aunque mi estilo es similar al de John Sansom, no estoy de acuerdo en poner criterios de unión en la cláusula WHERE. Creo que debería ser con la mesa unida para que esté organizada y fácil de encontrar.

También tiendo a poner paréntesis en nuevas líneas, alineadas con la línea por encima de ella y luego sangrando en la siguiente línea, aunque para declaraciones cortas, puedo mantener los paréntesis en la línea original. Por ejemplo:

SELECT
     my_column
FROM
     My_Table
WHERE
     my_id IN
     (
          SELECT
               my_id
          FROM
               Some_Other_Table
          WHERE
               some_other_column IN (1, 4, 7)
     )

Para las declaraciones CASE, doy una nueva línea y sangría para cada WHEN y ELSE, y alineo la END de nuevo a la CASE:

CASE
     WHEN my_column = 1 THEN 'one'
     WHEN my_column = 2 THEN 'two'
     WHEN my_column = 3 THEN 'three'
     WHEN my_column = 4 THEN 'four'
     ELSE 'who knows'
END
 2
Author: Tom H,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-07-19 07:56:04

Estoy trabajando en escribir un formateador SQL de código abierto (SQL-Server-solo en esta etapa) en C#, así que puse las consultas anteriores a través de él.

Emplea una estrategia similar a la del OP, es decir, que cada 'sección' tiene elementos secundarios sangrados debajo de ella. Cuando sea necesario, agrego espacio en blanco entre las secciones para ayudar a la claridad; estos no se agregarían cuando no hay uniones o condiciones mínimas de where.

Resultado:

SELECT
    ST.ColumnName1,
    JT.ColumnName2,
    SJT.ColumnName3

FROM SourceTable ST

INNER JOIN JoinTable JT
        ON JT.SourceTableID = ST.SourceTableID

INNER JOIN SecondJoinTable SJT
        ON ST.SourceTableID = SJT.SourceTableID
       AND ST.SourceTable2ID = SJT.SourceTable2ID

WHERE ST.SourceTableID = X
  AND JT.ColumnName3 = Y
  AND JT.Column3 = SJT.Column4

ORDER BY
    ST.ColumnName1
 2
Author: Ben Laan,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-07-19 14:53:33

Me doy cuenta de que llego muy tarde a este debate, pero me gustaría exponer mis ideas. Definitivamente estoy a favor de las comas al comienzo de la línea. Como dices Adam Ralph, es más fácil comentar un campo y también encuentro que es más difícil perder una coma accidentalmente cuando están al principio, mientras que esto no suena como un problema importante. He pasado horas en el pasado tratando de rastrear errores de sintaxis accidentales en largos procedimientos de T-SQL, donde he accidentalmente se perdió una coma al final de la línea (estoy seguro de que algunos de ustedes probablemente han hecho esto también). También estoy a favor de aliasing tanto como sea posible.

En general, sin embargo, me doy cuenta de que todo se debe a la preferencia personal, lo que funciona para algunos no para otros. Siempre y cuando puedas leer el código fácilmente y cada desarrollador muestre cierta consistencia en su estilo, creo que eso es lo más importante.

 2
Author: Sae1962,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-07-19 14:53:56

Tiendo a usar un diseño similar al tuyo, aunque incluso voy unos pasos más allá, por ejemplo:

select
        ST.ColumnName1
    ,   JT.ColumnName2
    ,   SJT.ColumnName3
from
                SourceTable     ST

    inner join  JoinTable       JT
        on  JT.SourceTableID    =   ST.SourceTableID

    inner join  SecondJoinTable SJT
        on  ST.SourceTableID    =   SJT.SourceTableID

where
        ST.SourceTableID    =   X
    and JT.ColumnName3      =   Y
    and JT.Column3          =   SJT.Column4

Tal vez parezca un poco exagerado al principio, pero en mi humilde opinión el uso de la tabulación de esta manera da el diseño más limpio y sistemático dada la naturaleza declarativa de SQL.

Probablemente termines con todo tipo de respuestas aquí. Al final, todo se reduce a las preferencias personales o acordadas por el equipo.

 2
Author: Adam Ralph,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-07-23 05:56:43

Si estoy haciendo cambios a T-SQL ya escrito, entonces sigo la convención ya utilizada (si hay una).

Si estoy escribiendo desde cero o no hay convención, entonces tiendo a seguir la convención dada en la pregunta, excepto que prefiero usar letras mayúsculas para palabras clave (solo una preferencia personal para la legibilidad).

Creo que con el formato SQL como con otras convenciones de formato de código, el punto importante es tener una convención, no lo que esa convención es (¡dentro de los reinos del sentido común, por supuesto!)

 1
Author: Russ Cam,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-02-06 11:10:14

Sí, puedo ver el valor de establecer su sql de alguna manera rigurosamente definida, pero seguramente la convención de nomenclatura y su intención son mucho más importantes. Como 10 veces más importante.

Basándonos en que my pet hates son tablas prefijadas por tbl, y procedimientos almacenados prefijados por sp - sabemos que son tablas y SPs. Nombrar objetos DB es mucho más importante que cuántos espacios hay

Solo mis valores de wor 0.02

 1
Author: MrTelly,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-02-06 11:12:15

Utilizo el ReFactor SQL de Red Gate dentro de SSMS, pero otra herramienta que hace reformating (y es un reemplazo para SSMS) es SQL Edit de Apex. Si está buscando código postal en línea, está El Simple-Talk SQL Prettifier.

 1
Author: K. Brian Kelley,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-03-21 17:38:52

Me gusta:

SELECT ST.ColumnName1, JT.ColumnName2, SJT.ColumnName3 --leave all selected columns on the same line
FROM 
    SourceTable ST
INNER JOIN JoinTable JT ON JT.SourceTableID = ST.SourceTableID
INNER JOIN SecondJoinTable SJT --only splitting lines when more than 1 condition
    ON ST.SourceTableID = SJT.SourceTableID
    AND JT.Column3 = SJT.Column4
WHERE
    ST.SourceTableID = X
    and JT.ColumnName3 = Y

Para obtener más código en un área de visualización más pequeña. También creo que las palabras clave deben estar en mayúsculas

 1
Author: user1400745,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-05-17 02:28:49

Hay muchos puntos buenos en este hilo. El único estándar que he estado tratando de convencer a la gente a utilizar es colocar la coma en la misma línea antes de cada columna. Así:

Select column1
   ,column2
   ,column3
   ,column4
   ,Column5 ...ect

Opuesto a:

Select column1,
   column2,
   column3, ect...

La razón por la que prefiero esta práctica es porque, si es necesario, puede comentar una línea y no habrá un problema de coma cuando la ejecute debido a que la coma correspondiente también se comenta. Sé que vi a otro usuario en el hilo que tenía hizo esto también, pero realmente no lo señaló. No es una gran revelación para llevar a la conversación, pero mis dos centavos. Gracias

 1
Author: AeternusMenti,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-04-12 15:59:41

Nadie ha hecho expresiones comunes de tabla (CTEs) todavía. A continuación lo incorpora junto con algunos otros estilos que uso:

@declare @tableVariable (
    colA1 int,
    colA2 int,
    colB1 int,
    colB2 nvarchar(255),
    colB3 nvarchar(255),
    colB4 int,
    colB5 bit,
    computed int
);

with

    getSomeData as (

        select        st.colA1, sot.colA2
        from          someTable st
        inner join    someOtherTable sot on st.key = sot.key

    ),

    getSomeOtherData as (

        select        colB1, 
                      colB2, 
                      colB3,
                      colB4,
                      colB5,
                      computed =    case 
                                    when colB5 = 1 then 'here'
                                    when colB5 = 2 then 'there'
                                    end
        from          aThirdTable tt
        inner hash 
         join         aFourthTable ft
                      on tt.key1 = ft.key2
                      and tt.key2 = ft.key2
                      and tt.key3 = ft.key3

    )

    insert      @tableVariable (
                    colA1, colA2, colA2, 
                    colB1, colB2, colB3, colB4, colB5, 
                    computed 
                )
    select      colA1, colA2, 
                colB1, colB2, colB3, colB4, colB5, 
                computed 
    from        getSomeData data1
    join        getSomeOtherData data2

Algunos puntos sobre el formato CTE:

  • En mis CTEs "with" está en una línea separada, y todo lo demás en el cte está sangrado.
  • Mis nombres de CTE son largos y descriptivos. Los CTE pueden obtener nombres complejos y descriptivos que son muy útiles.
  • Por alguna razón, me encuentro prefiriendo verbos para nombres CTE. Hace que parezca más animado.
  • Estilo similar con los paréntesis como lo hace Javascript con sus llaves. También es como hago los frenos en C#.

Esto simula:

func getSomeData() {

    select        st.colA1, sot.colA2
    from          someTable st
    inner join    someOtherTable sot on st.key = sot.key

}

Algunos puntos además del formato CTE:

  • Dos pestañas después de "seleccionar" y otras palabras clave. Eso deja suficiente espacio para "unirse internamente", "agrupar por", etc. Puedes ver un ejemplo anterior donde eso no es cierto. Pero "inner hash join" DEBERÍA parecer feo. Sin embargo, en este punto probablemente voy a experimentar con algunos de los estilos anteriores en el futuro.
  • Las palabras clave están en minúsculas. Su colorización por el IDE y su estado especial de sangría los resaltan lo suficiente. Reservo mayúsculas para otras cosas que quiero enfatizar basadas en la lógica local (de negocios).
  • Si hay pocas columnas, las pongo en una fila (getSomeData). Si hay un par más, me verticalizar ellos (getSomeOtherData). Si hay demasiada verticalización en una unidad, horizontalizo algunas columnas en la misma línea agrupada por lógica definida localmente (el segmento insert-select final). Por ejemplo, pondría la información a nivel de escuela en una línea, a nivel de estudiante en otra, etc.
  • Especialmente cuando verticalizo, prefiero la sintaxis "varname = colname + something" de sql server a "colname + something as varname".
  • Duplica el último punto si estoy tratando con una declaración de caso.
  • Si una cierta lógica se presta a un estilo 'matrix', me ocuparé de las consecuencias de escribir. Eso es más o menos de lo que está pasando con la sentencia case, donde los' whens 'y' then's están alineados.

Encuentro que estoy más decidido en mi estilo CTE que en otras áreas. No he experimentado con los estilos más similares a los planteados en la pregunta. Probablemente lo haga algún día y vea cómo me gusta. Probablemente estoy maldito para estar en un ambiente donde es una elección, aunque es una maldición divertida de tener.

 1
Author: pwilcox,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-05-23 12:02:39

Estoy totalmente de acuerdo con su esfuerzo para estandarizar el formato SQL dentro de su proyecto y en general.

También estoy muy de acuerdo con sus opciones de formato. He llegado a casi el mismo, salvo que también indent las declaraciones "join", y con ellos las declaraciones " on " un guión más.

Muy parecido al hecho de que usted va para minúsculas en las palabras clave - Que quiere que los gritó a usted. También prefiero los alias de la tabla en minúsculas-hace que sea mejor legibilidad

Muy parecido al hecho de que se usa sangría pequeña (4). Voy con (3).

Nix los términos 'interior' y 'exterior' como entonces son innecesarios.

Aquí está cómo habría formateado su instrucción select:

select
   st.ColumnName1,
   jt.ColumnName2,
   sjt.ColumnName3
from 
   SourceTable st
   join JoinTable jt on jt.SourceTableID = st.SourceTableID
   join SecondJoinTable sjt on
      st.SourceTableID = sjt.SourceTableID and
      jt.Column3 = sjt.Column4
where
   st.SourceTableID = X
   and jt.ColumnName3 = Y
;

Gracias por discutir esto.

 1
Author: dlink,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-09-27 12:59:40

Me gusta que mi SQL se formatee así, aunque siempre y cuando la intent sea fácilmente legible, la mayoría de cualquier formato funcionará. Realmente odio ver declaraciones creadas en el diseñador de consultas y luego me fui de esa manera. Si estoy editando otro procedimiento / vista / función / disparador, etc.., Voy a tratar de mantener el formato ya utilizado (a menos que sea realmente malo, entonces voy a volver a formatear todo el asunto).

Select Statement

SELECT ST.ColumnName1, JT.ColumnName2, SJT.ColumnName3
  FROM SourceTable ST INNER JOIN
       JoinTable JT ON JT.SourceTableID = ST.SourceTableID 
       INNER JOIN
       SecondJoinTable SJT ON ST.SourceTableID = SJT.SourceTableID
                          AND JT.Column3 = SJT.Column4
WHERE (ST.SourceTableID = X)
  AND (JT.ColumnName3 = Y);

Declaración de actualización

UPDATE TargetTable SET
       ColumnName1 = @value,
       ColumnName2 = @value2
 WHERE (Condition1 = @test);

Insértese Declaración

INSERT INTO TargetTable 
           (
             ColumnName1,
             ColumnName2,
             ColumnName3
           ) 
           values 
           (
             @value1,
             @value2,
             @value3
           );
 0
Author: Larry G,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-02-27 21:17:22

Creo que tener unas buenas reglas de formato son realmente importantes porque puedes detectar y corregir errores fácilmente. Como se dice - "Estás escribiendo código una vez, este código se lee entonces 10000000 de veces", por lo que siempre es bueno pasar algún tiempo en el formato. Los objetivos principales son:

  • Haz que tu código sea más fácil de leer y entender
  • Minimice el esfuerzo requerido para mantener o extender su código
  • Reducir la necesidad de que los usuarios y desarrolladores de un sistema consulten secundaria fuentes de documentación como comentarios de código o manuales de software

Algunas reglas que siempre uso:

  • Usar siempre . notación
  • Siempre use alias antes de la columna, so . notación
  • pongo and y or al final de la línea
  • No use corchetes innecesarios
  • No uses MAYÚSCULAS
  • Por lo general prefieren cte a subconsultas anidadas

Como ejemplo, aquí cómo formatear la consulta utilizada como ejemplo en esta pregunta:

select
    ST.ColumnName1,
    JT.ColumnName2,
    SJT.ColumnName3
from <schema>.SourceTable as ST
    inner join <schema>.JoinTable as JT on
        ST.SourceTableID = JT.SourceTableID
    inner join <schema>.SecondJoinTable as SJT on
        SJT.SourceTableID = ST.SourceTableID and
        SJT.Column4 = JT.Column3
where
    ST.SourceTableID = X and
    JT.ColumnName3 = Y

Y consulta" estudiantes":

select
    term,
    student_id,
    case
        when (ft_credits > 0 and credits >= ft_credits) or (ft_hours_per_week > 3 and hours_per_week >= ft_hours_per_week) then 'F'
        else 'P'
    end as [status]
from (
    select
        a.term,
        a.student_id,
        pm.credits as ft_credits,
        pm.[hours] as ft_hours_per_week,
        sum(a.credits) as credits,
        sum(a.hours_per_week) as hours_per_week
    from (
        select
            e.term, e.student_id, NVL(o.credits, 0) credits,
            case
                when NVL(o.weeks, 0) > 5 then
                    (NVL(o.lect_hours, 0) + NVL(o.lab_hours, 0) + NVL(o.ext_hours, 0)) / NVL(o.weeks, 0)
                else
                    0
            end as hours_per_week
        from enrollment as e
            inner join offering as o using (term, offering_id)
            inner join program_enrollment as pe on pe.student_id = e.student_id and pe.term = e.term and pe.offering_id = e.offering_id
        where
            e.registration_code Not in ('A7', 'D0', 'WL')
    ) as a
        inner join student_history as sh using (student_id)
        inner join program_major as pm on pm._major_code = sh.major_code_1 and pm.division_code = sh.division_code_1
    where
        sh.eff_term = 
            (
                select max(eff_term)
                from student_history as shi
                where
                    shi.student_id = sh.student_id and
                    shi.eff_term <= term
             )
    group by
        a.term,
        a.student_id,
        pm.credits,
        pm.[hours]
) as a
order by
    term,
    student_id
 0
Author: Roman Pekar,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-06-02 15:37:19

El número de opiniones diferentes es aterrador. Esto es lo que usa mi organización:

 SELECT ST.ColumnName1,
        JT.ColumnName2,
        SJT.ColumnName3
   FROM SourceTable ST
  INNER JOIN JoinTable JT ON JT.SourceTableID = ST.SourceTableID
  INNER JOIN SecondJoinTable SJT ON ST.SourceTableID = SJT.SourceTableID 
        AND JT.Column3 = SJT.Column4
  WHERE ST.SourceTableID = X
    AND JT.ColumnName3 = Y

Mantener la sangría de 8 caracteres es clave para la legibilidad en mi humilde opinión.

 0
Author: dthree,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-11-20 19:22:00

Mi estilo preferido:

SELECT
  ST.ColumnName1,
  JT.ColumnName2,
  SJT.ColumnName3
FROM
  SourceTable ST
INNER JOIN
  JoinTable JT
ON
  JT.SourceTableID = ST.SourceTableID
INNER JOIN
  SecondJoinTable SJT
ON
  ST.SourceTableID = SJT.SourceTableID
WHERE
  ST.SourceTableID = X
AND
  JT.ColumnName3 = Y
AND
  JT.Column3 = SJT.Column4
 0
Author: Brady,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-06-13 18:00:49
SELECT st.ColumnName1
      ,jt.ColumnName2
      ,sjt.ColumnName3
FROM   SourceTable st
JOIN   JoinTable jt ON jt.SourceTableID = st.SourceTableID
JOIN   SecondJoinTable sjt ON SstT.SourceTableID = sjt.SourceTableID
                              AND jt.Column3 = sjt.Column4
WHERE  st.SourceTableID = X
       AND jt.ColumnName3 = Y

Utilizo todas las mayúsculas para las palabras de acciones, joins o clauses, se destacan mejor. JOIN es lo mismo que INNER JOIN, por lo que INNER no necesita ser escrito, se supone, escribe OUTER JOIN o LEFT JOIN cuando lo necesites. También uso lowere case para mis nombres de alias. Common out front causa si comentas la última columna te quedas atascado con una coma arriba y la consulta falla.

 0
Author: DanTheMan,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-06-14 20:22:42

Un centenar de respuestas aquí ya, pero después de mucho toing y froing a lo largo de los años, esto es lo que he decidido:

SELECT      ST.ColumnName1
          , JT.ColumnName2
          , SJT.ColumnName3

FROM        SourceTable       ST
JOIN        JoinTable         JT  ON  JT.SourceTableID  =  ST.SourceTableID
JOIN        SecondJoinTable  SJT  ON  ST.SourceTableID  =  SJT.SourceTableID
                                  AND JT.Column3        =  SJT.Column4

WHERE       ST.SourceTableID  =  X
AND         JT.ColumnName3    =  Y

Sé que esto puede crear diferencias desordenadas, ya que una tabla adicional podría hacer que vuelva a sangrar muchas líneas de código, pero por mi facilidad de lectura me gusta.

 0
Author: Codemonkey,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-11-16 16:39:40

Mejor tarde que nunca. Uso un estilo diferente y lo adopté de un muy buen desarrollador SQL con el que solía trabajar. Alineo a la derecha las palabras clave y no uso letras MAYÚSCULAS para la facilidad de escribir. Las palabras clave serán resaltadas por el editor y no veo la necesidad de que estén en MAYÚSCULAS a menos que realice muchas ediciones en editores de texto que no admiten funciones de resaltado de palabras clave. No intento hacerlo compacto, sino más bien más legible y alineado verticalmente tanto como posible. Aquí hay un ejemplo de una selección tomada de @BenLaan respuesta escrita en mi formato:

select st.ColumnName1
       , jt.ColumnName2
       , sjt.ColumnName3
  from SourceTable st
         inner join
       JoinTable jt
         on jt.SourceTableID = st.SourceTableID
         inner join
       SecondJoinTable sjt
         on st.SourceTableID = sjt.SourceTableID
         and st.SourceTable2ID = sjt.SourceTable2ID
 where st.SourceTableID = X
       and jt.ColumnName3 = Y
       and jt.Column3 = sjt.Column4
 order by st.ColumnName1

Tratar de conformar a todo el equipo para seguir el mismo patrón de formato es lo más difícil. Yo seguiría cualquier formato, si todos los demás siguieran el mismo camino, pero nunca ha sido la misma historia.

ACTUALIZAR: Reescribiendo una de las consultas complejas mencionadas en publicaciones anteriores:

select
       term
       , student_id
       , case
           when((ft_credits > 0 and credits >= ft_credits) or (ft_hours_per_week > 3 and hours_per_week >= ft_hours_per_week))
             then 'F'
           else 'P'
         end as status
  from (select term
               , student_id
               , pm.credits AS ft_credits
               , pm.hours AS ft_hours_per_week
               , SUM(credits) AS credits
               , SUM(hours_per_week) AS hours_per_week
          from (select e.term
                       , e.student_id
                       , nvl(o.credits, 0) credits
                       , case
                           when nvl(o.weeks, 0) > 5 
                             then (nvl(o.lect_hours, 0) + nvl(o.lab_hours, 0) + nvl(o.ext_hours, 0)) / nvl(o.weeks, 0)
                           else 0
                        end as hours_per_week
                  from enrollment as e
                         inner join 
                       offering as o using (term, offering_id)
                         inner join
                       program_enrollment as pe 
                         on e.student_id = pe.student_id 
                         and e.term = pe.term 
                         and e.offering_id = pe.offering_id
                 where e.registration_code not in ('A7', 'D0', 'WL')
                )
                  inner join 
                student_history as sh using (student_id)
                  inner join 
                program_major as pm 
                  on sh.major_code_1 = pm._major_code and sh.division_code_1 = pm.division_code
         where sh.eff_term = (select max(eff_term)
                                from student_history as shi
                               where sh.student_id = shi.student_id
                                     and shi.eff_term <= term)
         group by term, student_id, pm.credits, pm.hours
        )
 order by term, student_id
 0
Author: rageit,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-07-19 15:30:37

Este es el formato que uso. Por favor, comente si se puede mejorar.

CREATE PROCEDURE [dbo].[USP_GetAllPostBookmarksByUserId]
    @id INT,
    @startIndex INT,
    @endIndex INT
AS
BEGIN

    SET NOCOUNT ON

    SELECT      *
    FROM
            (   SELECT      ROW_NUMBER() OVER ( ORDER BY P.created_date ) AS row_num, P.post_id, P.title, P.points, p.estimated_read_time, P.view_count, COUNT(1) AS "total_attempts" -- todo
                FROM        [dbo].[BOOKMARKED] B
                INNER JOIN  [dbo].[POST] P
                ON          B.entity_id = P.post_id
                INNER JOIN  [dbo].[ATTEMPTED] A
                ON          A.entity_id = P.post_id
                WHERE       B.user_id = 1 AND P.is_active = 1
                GROUP BY    P.post_id, P.title, P.points, p.estimated_read_time, P.view_count
            )   AS PaginatedResult
    WHERE       row_num >= @startIndex
    AND         row_num < @endIndex
    ORDER BY    row_num

END
 0
Author: CodeZila,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-08-08 07:51:22

Parece que la mayoría de ustedes todavía trabajan en monitores que solo admiten 800x600. Mis monitores harán 1920x1080, así que quiero usar todo ese espacio a la derecha.

¿qué tal esto:

select col1, col2, col3
, case when x = 1 then 'answer1'
       else 'answer2'
  end
, col4, col5, col6, col7
from table1 t1
inner join table2 t2 on t1.col1 = t2.col1 and t1.col2 and t2.col2
where t1.col5 = 19 and t1.col7 = 'Bill Gates'
 -5
Author: Bill J Blender,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-02-17 16:26:41