web-dev-qa-db-fra.com

Bonne pratique d'indentation des instructions SQL

Quelle est la pratique acceptée pour mettre en retrait les instructions SQL? Par exemple, considérez l'instruction SQL suivante:

SELECT column1, column2
FROM table1
WHERE column3 IN
(
SELECT TOP(1) column4
FROM table2
INNER JOIN table3
ON table2.column1 = table3.column1
)

Comment cela devrait-il être mis en retrait? Merci beaucoup.

67
MagicAndi
SELECT column1
     , column2
FROM table1
WHERE column3 IN
(
    SELECT TOP(1) column4
    FROM table2
    INNER JOIN table3
    ON table2.column1 = table3.column1
)

J'aime avoir tout "," devant, de cette façon, je ne les recherche jamais en cas d'erreur à la ligne X de l'éditeur SQL.


Ceci est un exemple pour ceux qui n'utilisent pas ce type d'instructions SQL d'écriture. Les deux contiennent une erreur de virgule manquante.

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
(
    ...
)

J'ai trouvé plus facile et plus rapide au premier exemple. J'espère que cet exemple vous montrera plus mon point de vue.

42
SELECT column1, column2
FROM table
WHERE column3 IN (
    SELECT TOP(1) column4
    FROM table2
    INNER JOIN table3 ON table2.column1 = table3.column1
)

C'est assez court et facile à lire. Je ferais des ajustements s'il y avait plus de colonnes sélectionnées ou plus de conditions de jointure.

25
Bill the Lizard

Je ne sais pas s'il existe une pratique acceptée, mais voici maintenant comment je procéderais:

SELECT 
    column1, 
    column2 
FROM 
    table1 
WHERE 
    column3 IN 
    ( 
     SELECT TOP(1) 
         column4 
     FROM 
         table2 
         INNER JOIN 
         table3 
             ON table2.column1 = table3.column1 
    )
20
Codewerks

J'aime avoir des "fleuves" d'espaces blancs dans le code. Cela facilite un peu la numérisation.

SELECT column1,
       column2
  FROM table1
 WHERE column3 IN (SELECT column4
                     FROM table2
                     JOIN table3
                       ON table2.column1 = table3.column1);
19
jalbert

J'aime la forme de jalbert d'aligner les mots-clés sur leur droite. J'ajouterais également que j'aime les ET et les OU à gauche (certaines personnes les mettent à droite.) De plus, j'aime aligner mes signes égaux lorsque cela est possible.


SELECT column1, 
       column2  
  FROM table1, table2 
 WHERE table1.column1 = table2.column4 
   AND table1.col5    = "hi" 
    OR table2.myfield = 678 
16
Slapout

Ceci est ma méthode personnelle. En fonction de la longueur de la condition de jointure, je l'indente parfois sur la ligne ci-dessous.

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
  )
10
LeppyR64

J'ai écrit une norme de code pour notre boutique qui est orientée à l'extrême vers la lisibilité/"découvrabilité" (cette dernière étant principalement utile dans les instructions d'insertion-sélection):

SELECT 
    column1, 
    column2
FROM 
    table1
WHERE 
    column3 IN
    (
        SELECT TOP(1) 
            column4
        FROM 
            table2
            INNER JOIN table3 ON table2.column1 = table3.column1
    )

Sur les requêtes plus complexes, il devient plus évident de savoir comment cela est utile:

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
    )

Une fois que vous passez à des systèmes avec plus d'une seule jointure dans la plupart de vos requêtes, mon expérience montre que l'utilisation libérale de l'espace vertical est votre meilleur ami avec SQL complexe.

7
Mike Burton

Si vous avez une longue instruction SQL que vous souhaitez reformater sans toute la frappe et la tabulation, vous pouvez la mettre dans ce site Web et obtenir un résultat bien formaté. Vous pouvez expérimenter différents formats pour voir ce qui rend votre texte le plus lisible.

Edit: je crois que this est l'emplacement 2014 du formateur SQL.

7
DOK

Le formatage SQL est un domaine où il y a beaucoup de variance et de désaccord ... Mais fwiw, j'aime me concentrer sur la lisibilité et je pense que quoi que vous fassiez, toujours conforme à toutes les règles qui réduisent la lisibilité est, comme le dit le vieux cliché, une "cohérence insensée" ("La cohérence insensée est un hobgobelin pour les esprits simples")

Donc, au lieu de les appeler règles, voici quelques lignes directrices. Pour chaque clause Major d'une instruction SQL (Select, Insert, Delete, From, Where, Have, Group BY, Order By, ... j'en manque peut-être) devrait être FACILEMENT identifiable. Je les ai donc généralement mis en retrait au plus haut niveau, tous même les uns avec les autres. Ensuite, à l'intérieur de chaque clause, j'indente uniformément la sous-structure logique suivante ... et ainsi de suite .. Mais je me sens libre de changer (et souvent le fais) le modèle si, dans tous les cas, il serait plus lisible de le faire ... Les déclarations de cas complexes en sont un bon exemple. Parce que tout ce qui nécessite un défilement horizontal réduit considérablement la lisibilité, j'écris souvent des expressions Case complexes (imbriquées) sur plusieurs lignes. Quand je le fais, j'essaie de garder le début d'une telle instruction en retrait en fonction de sa place logique dans l'instruction SQL, et en retrait du reste des lignes de l'instruction quelques caractères furthur ...

Le code de la base de données SQL existe depuis longtemps, car avant les ordinateurs avaient des minuscules, il y a donc une préférence historique pour les mots clés en majuscule, mais je préfère la lisibilité à la tradition ... (et chaque outil que j'utilise des codes de couleur les mots clés maintenant en tous cas)

J'utiliserais également des alias de table pour réduire la quantité de texte que l'œil doit numériser afin de bloquer la structure de la requête, tant que les alias ne créent pas de confusion. Dans une requête avec moins de 3 ou 4 tables, les alias de caractère unique sont très bien, j'utilise souvent la première lettre de la table si toutes les autres tables commencent par une lettre différente ... encore une fois, ce qui contribue le plus à la lisibilité. Enfin, si votre base de données le prend en charge, de nombreux mots clés sont facultatifs (comme "Inner", "Outer", "As" pour les alias, etc.) "Into" (à partir de Insert Into) est facultatif sur Sql Server - mais pas sur Oracle) Soyez donc prudent lorsque vous utilisez ce code si votre code doit être indépendant de la plate-forme ...

Votre exemple, j'écrirais comme:

Select column1, column2
From table1 T1
Where column3 In (Select Top(1) column4
                  From table2 T2
                     Join table3 T3
                         On T2.column1 = T3.column1)

Ou

Select column1, column2
From table1 T1
Where column3 In 
     (Select Top(1) column4
      From table2 T2
         Join table3 T3
            On T2.column1 = T3.column1)

S'il y avait beaucoup plus de colonnes sur la clause select, je mettrais en retrait la deuxième ligne et les lignes suivantes ... Je n'adhère généralement à aucune règle stricte (une colonne par ligne) car le défilement vertical est presque aussi mauvais pour la lisibilité que le défilement horizontal est, surtout si seules les dix premières colonnes de l'écran contiennent du texte)

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)

Formater le code de quelque manière que ce soit le rend le plus lisible ...

6
Charles Bretana

Comme la plupart ci-dessus ont aligné les noms des colonnes de retour, je trouve que l'alignement des noms et des conditions des tables aide beaucoup à la lisibilité.

SELECT 
    column1, 
    column2
FROM 
    table1
WHERE 
    column3 IN
    (
        SELECT TOP(1) 
            column4
        FROM 
            table2 INNER JOIN 
            table3 ON table2.column1 = table3.column1
    )

Et pour quand les conditions d'adhésion deviennent longues.

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
    )
5
Jens Frandsen

J'aime avoir les différentes parties de ma requête alignées verticalement. J'ai tendance à utiliser une taille de tabulation de 8 espaces pour SQL qui semble bien fonctionner.

SELECT  column1, 
        column2
FROM    table1
WHERE   column3 IN
(
        SELECT TOP(1) column4
        FROM    table2
        INNER JOIN table3
        ON      table2.column1  = table3.column1
)
5
Jack Ryan

Exemple mettant en retrait un SQL très très très complexe:

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

Voici mon coup à ceci:

select column1, column2
    from table1
    where (column3 in (
        select top(1) column4
            from table2
            inner join table3
                on (table2.column1 = table3.column1)
    ))
;
  • Tout en minuscules, car il est plus facile de lire les caractères en minuscules (et nous avons le surlignage de code pour mettre en évidence les mots clés) également plus facile à taper
  • Chaque restriction ou option sur un mot clé (comme le from sur le select ou le on sur la jointure) est mise en retrait pour montrer leur dépendance sur le mot clé outward
  • Le support de fermeture est au même niveau de retrait que l'ouverture où
  • Utilisez des crochets pour les clauses where et on pour améliorer la lisibilité
  • Faites en sorte que le point-virgule ferme l'instruction select avec le même retrait afin que plusieurs instructions puissent être mieux distinguées (si vous avez besoin d'un point-virgule dans votre langue comme SAS PROC SQL le fait))
  • Il est toujours assez compact et ne s'étend pas sur toute la page
5
John Doe

Bien sûr, cela se résume à des préférences personnelles. Et si dans une équipe, c'est quelque chose qui devrait être convenu entre les membres par souci de cohérence. Mais ce serait ma préférence:

SELECT column1, column2
FROM   table1
WHERE  column3 IN(SELECT     TOP(1) column4
                  FROM       table2
                  INNER JOIN table3 ON
                             table2.column1 = table3.column1
                 )
4
Bullines

Je formaterais comme ceci:

SELECT
    column1, 
    column2
FROM 
    table1
WHERE 
    column3 IN (SELECT TOP(1) 
                    column4 
                FROM 
                    table2 
                    INNER JOIN table3 ON table2.column1 = table3.column1)

ou comme ça:

SELECT
    column1, 
    column2
FROM 
    table1
WHERE 
    column3 IN (SELECT TOP(1) column4 
                FROM table2 
                INNER JOIN table3 ON table2.column1 = table3.column1)
3
Mitch Wheat

Je viens de le faire passer par mon prettifier SQL et il est sorti comme ça ....

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

..... Mais je n'ai pas trouvé de moyen d'intégrer les couleurs dans StackOverflow.

2
Phil_Factor

Ceci est ma préférence normale:

....SELECT column1
........,column2
....FROM table1
....WHERE column3 IN (
........SELECT TOP(1) column4
........FROM table2
........INNER JOIN table3
............ON table2.column1 = table3.column1
....)

Bien que stackoverflow perturbe la mise en forme avec un espace de tête supplémentaire, j'ai donc mis quelques périodes pour que vous puissiez voir la mise en forme réelle ...

2
Cade Roux

Ce lien est le meilleur que j'ai trouvé. http://www.sqlinform.com/free_online_sw.html

2
Ravi Shankar Kota

Oui, c'est assez subjectif ... Mais voici mes 2 cents:

SELECT
   Column1,
   Column2
FROM Table1
WHERE 
   Column3 IN (
      SELECT Column4
      FROM Table2
      JOIN Table3 ON
         Table2.Column1 = Table3.Column1
   )

Mais, vraiment, je le réécrirais probablement sans l'IN:

SELECT
   Column1,
   Column2
FROM Table1
JOIN Table2 ON
   Table1.Column3 = Table2.Column4
JOIN Table3 ON
   Table2.Column1 = Table3.Column1

Fondamentalement, mes règles sont les suivantes:

  • Capitaliser les mots clés
  • Les colonnes vont sur des lignes individuelles, mais les modificateurs SELECT (SELECT TOP 100, SELECT DISTINCT, etc.) ou les colonnes simples (SELECT 1, SELECT Id, SELECT *, etc.) vont sur la même ligne
  • Conditions de jointure en retrait sous la clause JOIN
  • Utilisez JOIN pour INNER JOIN (car c'est le plus commun) et spécifiez complètement les autres (LEFT OUTER JOIN, FULL OUTER JOIN, etc.)
  • Ouvrez les parens sur la même ligne, fermez les parens sur une ligne distincte. Si vous avez un alias, l'alias va de pair.
2
Mark Brackett

Je ne sais pas s'il y a une norme mais j'aime le faire de cette façon;

SELECT column1, column2
  FROM table1
WHERE column3 IN
(
    SELECT TOP(1) column4
      FROM table2
    INNER JOIN table3
      ON table2.column1 = table3.column1
)

parce que je peux mieux lire et analyser le SQL.

1
Nelson Miranda

Eh bien, bien sûr, cela dépend de la requête.

Pour les requêtes simples, un schéma d'indentation très formel est juste plus problématique qu'il ne vaut et peut réellement rendre le code moins lisible, pas plus. Mais à mesure que la complexité augmente, vous devez commencer à être plus prudent avec la façon dont vous structurez l'instruction, pour vous assurer qu'elle sera à nouveau lisible plus tard.

1
Joel Coehoorn
SELECT
    Column1,
    Column2
FROM
    Table1
WHERE
    Column3 IN
    (
        SELECT TOP (1)
            Column4
        FROM 
            Table2
        INNER JOIN 
            Table3
        ON
            Table2.Column1 = Table3.Column1
    )
1
S. Goldberg

Ce que je fais habituellement,

print("SELECT column1, column2
       FROM table1
       WHERE column3 IN (SELECT TOP(1) column4
                         FROM table2 INNER JOIN 
                              table3 ON table2.column1 = table3.column1)");
0
Amy

C'est une question de goût.

C'est ma préférence.

SELECT 
  column1
 ,column2
FROM
  table1
WHERE column3 IN (
                 SELECT TOP(1) column4
                 FROM 
                   table2
                   INNER JOIN table3
                 ON table2.column1 = table3.column1
                 )
0
JosephStyons