SQL语句缩进的好习惯[关闭]


73

缩进SQL语句的公认做法是什么?例如,考虑以下SQL语句:

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

应该如何缩进?非常感谢。


我觉得有这么多答案都是同等有效的,而且更多是您的偏爱!这是一种典型的语言,它允许您将大量代码编写到一个语句中,这既可以是祝福,也可以是诅咒。相当简单的语句占用多行,而复杂的语句占用一页或更多页。与其他语言一样,语句通常只占一行,有时只占一行,因此缩进的变化较少;大多数分歧都围绕着一些小问题,例如括号应该在行尾还是在行尾。
AaronLS 2010年

1
好的问题顺便说一句..预计也将看到更多更新并插入缩进..
nawfal 2012年

让工具代替您手动进行操作。有一些免费工具(也在线),例如www.sqlinform.com
Guido,

@Guido我不同意。如果您花时间一直通过缩进工具运行它,则会浪费时间。另一方面,如果您不缩进代码,那么您就在看草率。即使每隔五分钟通过缩进工具运行一次,您仍然会放慢脚步,停下来思考一下未格式化的代码。依靠他人的工具也是拐杖。我认为这会养成不良习惯,尤其是当您改用其他语言时。
person27年

Answers:


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

我喜欢将所有的“,”放在前面,这样,当SQL编辑器在X行出现错误时,我就永远不会搜索它们。


对于那些不使用这种写SQL语句的人来说,这是一个示例。两者都包含缺少逗号的错误。

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

在第一个示例中,我发现更加轻松快捷。希望本示例向您展示更多我的观点。


1
是的,前逗号看起来很傻,但是从长远来看,它非常容易管理。
cfeduke

3
使用逗号开头,您总是知道它们在哪里,而不必去寻找它们。
Ken Gentle

4
有时您搜索缺少逗号的地方...很明显它们在最前面。由于逗号,您在SQL语句中出错的那一天,您会想到我的;)
Patrick Desjardins,

4
如果您具有合理的“垂直”样式,则可以完全扫描行尾逗号,特别是如果您习惯于为每列使用列标签。
Mike Burton 2010年

7
令我担心的是,很多人认为逗号是格式化SQL的最重要的内容。
Mike Burton

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

这很短,很容易阅读。如果选择了更多的列或更多的连接条件,我会进行调整。


我喜欢使用相同的缩进方案。
yfeldblum

许多教科书都使用此功能或类似功能。我喜欢保持简单。:)
比尔蜥蜴,

我倾向于个人使用这种样式,除非我将开头放到新的一行上
。– MagicAndi

如果找到开口(按自己的路线显示:),我不会更改它
蜥蜴法案

是的,每个主要关键字都换行,嵌套的部分缩进。当列名的长列表位于单独的行上时,我不喜欢所有的上下滚动。我想在一个屏幕上看到尽可能多的东西。
DOK

21

不确定是否存在接受的做法,但是现在这是我的做法:

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

我最喜欢这种练习。不幸的是,我使用的所有SQL beutifiers都不支持这种标识。唯一的区别是,我使用小写字母的关键字,因为我讨厌这样尖叫的SELECT :)
mnaoumov

19

我喜欢在代码中包含空白的“ rivers”。它使扫描更加容易。

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

1
是否有支持这种缩进/对齐样式的IDE?
viam0Zah 2010年

我将更进一步,将“ column1”后的逗号(,)包裹到下一行,以保持河流的畅通。
nclu

17

我喜欢jalbert排列其右边关键字的形式。我还要补充一点,我喜欢左边的AND和OR(有些人把它们放在右边。)此外,我希望在可能的情况下排列我的等号。


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

1
我个人也很喜欢-如果关键词在您期望的位置准确排列,我发现快速扫描代码很有用
Cruachan

1
我也喜欢这个,但是你怎么做到的?您实际上是在手动隔开每一行的开头吗?似乎很麻烦。如果有一种简单的格式格式化方法,我想知道
billynoah,2015年

奇怪的是,所有选择,插入,更新,删除的关键字都具有相同的长度。:)
Natix

很好,但是有问题。在这里,如果您使用不同的编辑器(terminal / sublime / atom / mysqlworkbench / navicat / etc),您将获得不同的结果,因为根据所使用的视觉字体,选项卡/空格都将以不同的方式显示。(长寿命空间;-P)
JayRizzo

经过大约10年的SQL经验,我已经在这里安顿了下来,但是我使用JOIN具有显式联接而不是逗号分隔的隐式联接的语法。显式联接将结构与业务逻辑分开,它们使忘记联接变得更加困难。有时,我还会将整个查询放在LEFT JOIN,,右边ORDER BY,然后GROUP BY完全在河的左侧流动。
durette

13

这是我的个人方法。根据连接条件的长度,有时我会在下面的行中对其进行缩进。

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
  )

这就是我的方式(杰森的方式)。子句关键字在各自的行中。子句组件缩进。逗号分隔或布尔分隔列表是每个项目一行。括号在同一行上(而不是在自己的行上)。
Pistos

这几乎与我使用的变体相同。当TSQL关键字位于单独的行上时,它使代码更具可读性。与您的变体的唯一区别是,我在列名的前面加了逗号。原因是我注释掉最后一列的频率要高于第一列。
格林

8

我为我们的商店编写了一个代码标准,该代码标准偏向于可读性/“可发现性”(后者主要在insert-select语句中有用):

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,
    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
    )

在大多数查询中,如果您将系统转移到具有多个联接的系统,那么根据我的经验,自由使用垂直空间是使用复杂SQL的最好朋友。


7

如果您有一个冗长的SQL语句想要在不进行所有键入和制表的情况下重新格式化,则可以将其打入该网站并获得格式正确的结果。您可以尝试各种格式,以查看哪种格式的文字更具可读性。

编辑:我相信是SQL格式化程序的2014年位置。


酷链接。不知道我会自己使用它,但可以添加一些书签。
Pistos

现在链接已断开。是否存在备份?
Ernir 2014年

@Ernir感谢您的提示。我想我找到了新位置。查看我添加到答案中的链接。
DOK

6

SQL格式化是一个存在很大差异和分歧的领域。但是,首先,我喜欢关注可读性,并且认为,无论您做什么,始终遵循任何降低可读性的规则,就像老套话一样,一个“愚蠢的一致性”(“愚蠢的一致性是简单头脑的妖精”)

因此,这里不是一些规则,而是一些准则。对于SQL语句中的每个Major子句(“选择”,“插入”,“删除”,“从”,“位置”,“具有”,“分组依据”,“订购依据…………我可能会遗漏一些”),应该可以轻松识别。因此,我通常会在最高级别缩进,甚至彼此缩进。然后在每个子句中,我均匀地缩进下一个逻辑子结构……等等。但是,如果在任何情况下这样做都更容易阅读,我可以自由地(并且经常这样做)更改模式。复杂案例陈述就是一个很好的例子。因为任何需要水平滚动的操作都会极大地降低可读性,所以我经常在多行上编写复杂(嵌套)的Case表达式。当我这样做时,我会根据该语句在SQL语句中的逻辑位置,尝试使该语句的开头保持缩进,

SQL Database代码已经存在很长时间了,因为在计算机使用小写字母之前,因此在历史上偏爱使用大写字母作为关键字,但是与传统相比,我更喜欢可读性...(而且我现在使用的每个工具都使用颜色代码作为关键字无论如何)

我也将使用Table别名来减少眼睛以查询查询的结构而需要扫描的文本量,只要别名不会造成混乱即可。在少于3或4个表的查询中,单字符别名很好,如果所有其他表都以不同的字母开头,那么我经常使用表的第一个字母...同样,无论哪种方式都有助于提高可读性。最后,如果您的数据库支持它,则许多关键字是可选的(例如,“ Inner”,“ Outer”,“ As”等别名)。“ Into”(来自Insert Into)在Sql Server上是可选的-但不是在Oracle上),因此如果您的代码需要与平台无关,请谨慎使用...

您的示例,我将写为:

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

要么

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

如果select子句上有更多列,我将缩进第二行和后续行...我通常不遵守任何严格的规则(每行一列),因为垂直滚动几乎与水平滚动一样不利于可读性是,尤其是如果屏幕的前十列中只有任何文本)

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)

以任何使其最易读的方式格式化代码...


对于所有这一切,您的关键字之一UPPERlower全部可以帮助您直观地识别关键字。我更喜欢UPPER作为EYE_GRABBING方法。
JayRizzo

5

我喜欢将查询的不同部分垂直排列。对于SQL,我倾向于使用8个空格的制表符大小,这似乎效果很好。

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

5

缩进非常非常复杂的SQL的示例:

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

为什么您显然将INNER JOIN放在与FROM相同的缩进级别中?
IgorJerosimić13年

5

由于以上大多数内容都对返回列名称进行了排列,因此我发现对表名称和条件进行排列对提高可读性有很大帮助。

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

2
这些连接不可读
IgorJerosimić13年

@IgorJerosimić我个人不会使用这种样式,但是我在这里觉得它很容易阅读-Jens只是排列表名和条件,以便您可以垂直扫描它们。
乔丹·格雷

同意伊戈尔(Igor)的想法,无法弄清楚参加者
马克斯·亚历山大·汉纳

5

这是我的意思:

select column1, column2
    from table1
    where (column3 in (
        select top(1) column4
            from table2
            inner join table3
                on (table2.column1 = table3.column1)
    ))
;
  • 一切都小写,因为它更容易阅读小写字符(并且我们突出显示了代码以强调关键字)也易于键入
  • 缩进关键字的每个限制或选项(例如select上的from或联接上的on)都会缩进,以显示其对outward关键字的依赖性
  • 闭合支架与开口处的压痕高度相同
  • 在括号内和子句中使用括号以增加可读性
  • 让分号在相同的缩排处关闭选择语句,以便更好地区分多个语句(如果您需要像SAS PROC SQL这样的语言,请使用分号)
  • 它仍然非常紧凑,不会延伸到整个页面

与第一个示例相比,我认为此操作中的所有内容都是小写形式。你是认真的吗?缩进似乎是故意的,比认可的答案难读得多。紧凑?对我来说,它看起来像整个页面一样-尽管不是垂直的,而是水平的。
Max Alexander Hanna

4

当然,这取决于个人喜好。如果是团队合作,则出于一致性的考虑,应该在成员之间达成一致。但这是我的偏爱:

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

3

我会这样格式化:

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)


2

是的,这很主观...但这是我的2美分:

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

但是,实际上,我可能会在没有IN的情况下重写它:

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

基本上,我的规则是:

  • 大写关键字
  • 列在单独的行上,但是SELECT修饰符(SELECT TOP 100,SELECT DISTINCT等)或单列(SELECT 1,SELECT ID,SELECT *等)在同一行上
  • 在JOIN子句下缩进的连接条件
  • 对内部联接使用JOIN(因为这是常见的联接),并完全指定其他联接(向左联接,全联接等)。
  • 在同一行上打开括号,在单独的行上关闭括号。如果您有别名,则别名与紧密括号一起使用。

1
大写关键字在PostGresql上不起作用,因为大小写敏感,因此必须在“”中。注意数据库的类型。
Patrick Desjardins,

1
文档似乎没有提到该怪癖-甚至在示例中都使用了大写的关键字:postgresql.org/docs/8.0/static / ...
Mark Brackett

2

这是我通常的偏好:

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

1

好吧,当然这取决于查询。

对于简单的查询,一个高度正式的缩进方案只会带来更多麻烦,而且实际上会使代码的可读性更,而不是更多。但是,随着复杂度的增长,您需要开始更加谨慎地构造语句的结构,以确保以后再次可读。


1

我不知道是否有一个标准,但我喜欢这样做。

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

因为我可以更好地阅读和分析SQL。


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

0

我通常要做的是

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

0

这是一个品味问题。

这是我的偏爱。

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

-3

这就是我们在这里要做的:

选择
        第1栏,
        第2栏,
        当COLUMN5 ='X'时
                        和
                        COLUMN6 ='Y'
                然后“一个”
                当COLUMN5在(
                                'AAA',
                                'BBB'
                        )
                然后是“两个”
                否则“三个”
        以COLUMN7结尾
从
        表格1
哪里
        第2栏的(
                选择顶部(1)
                        第4栏
                从
                        表2
                        内部联接
                        表3
                                上
                                        TABLE2.COLUMN1 = TABLE3.COLUMN1
                                        和
                                        TABLE2.COLUMN2
                                                之间
                                                        表3.第2列
                                                        和
                                                        表3.第3列
        )

我们的想法是:将sql关键字保留为小写,将所有变化的(因此更“有趣”)诸如表名或列名都使用大写。代码在这里可能看起来有些“炸破”,但是如果您具有比本示例更长的更长名称(包括架构等)的复杂查询,它会提高可读性。并且:根据对象的“级别”缩进所有对象。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.