SQL 语句缩进良好实践

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

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

这个应该怎么缩进? 非常感谢。

75654 次浏览

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

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
)
SELECT column1, column2
FROM table
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
)
SELECT column1
, column2
FROM table1
WHERE column3 IN
(
SELECT TOP(1) column4
FROM table2
INNER JOIN table3
ON table2.column1 = table3.column1
)

我喜欢有所有的 “ ,”在前面,这样我从来没有搜索他们时,在行 X 错误从 SQL 编辑器。


对于那些不使用此类编写 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
(
...
)

在第一个例子中我发现更容易和更快。希望这个例子能给你更多我的观点。

我通常会这么做,

print("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
)

我的格式是这样的:

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)

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

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

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

我喜欢在代码中有“河流”一样的空白区域,这样扫描起来会更容易一些。

SELECT column1,
column2
FROM table1
WHERE column3 IN (SELECT column4
FROM table2
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
)

这是品味的问题。

这是我的偏好。

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

我喜欢让查询的不同部分垂直排列。我倾向于为 SQL 使用8个空格的制表符,这看起来效果不错。

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 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 (因为它是常见的) ,并完全指定其他(左外连接、完全外连接等)
  • 在同一行上打开括号,在另一行上关闭括号。如果你有别名,别名就用括号。

SQL 格式化是一个存在大量差异和分歧的领域... ... 但是,我喜欢关注可读性,并且认为无论你做什么,始终遵守任何降低可读性的规则,就像老话说的那样,是一种“愚蠢的一致性”(“愚蠢的一致性是简单头脑的妖怪”)

因此,与其称之为规则,这里有一些指导方针。 For each Major clause in a SQL statement (Select, Insert, Delete, From, Where, Having, Group BY, Order By, ... I may be missing a few) should be EASILY identifiable. So I generally indent them at the highest level, all even with each other. Then within each clause, I indent the next logical sub structure evenly... and so on.. But I feel free to (and often do) change the pattern if in any individual case it would be more readable to do so... Complex Case statements are a good example. Because anything that requires horizontal scrolling reduces readability enormously, I often write complex (nested) Case expressions on multiple lines. When I do, I try to keep the beginning of such a statement hanging indent based on it's logical place in the SQL statement, and indent the rest of the statement lines a few characters furthur...

SQL 数据库代码已经存在了很长一段时间,因为在计算机还没有小写之前,所以历史上对大写关键字的偏好,但我更喜欢可读性超过传统... (而且现在我使用的每个工具都用颜色代码关键字)

我还将使用 Table 别名来减少眼睛必须扫描的文本数量,以便理解查询的结构,只要别名不会造成混淆。在少于3或4个表的查询中,使用单字符别名是可以的,如果所有其他表都以不同的字母开头,我通常会使用表的第一个字母... ... 同样,任何最有助于提高可读性的字母。最后,如果您的数据库支持它,那么许多关键字是可选的,(比如别名的“內”、“外”、“ 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)

以最易读的方式格式化代码。

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


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

我为我们的工作室编写了一个代码标准,偏向于极端的可读性/“可发现性”(后者主要用于插入-选择语句) :

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 最好的朋友。

如果您有一个冗长的 SQL 语句,希望在不需要所有输入和制表符的情况下重新格式化该语句,那么您可以将其打入 本网站,并得到一个格式化得很好的结果。您可以尝试使用各种格式,看看哪种格式使您的文本最具可读性。

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

我刚刚把它通过我的 SQL 美化器,它出来这样... 。

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

但是我还没有找到一种方法把颜色加入到 StackOverflow 中。

缩进一个非常非常非常复杂的 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
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
)

以及当连接条件变长时。

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
)

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

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
)

我们的想法是: 将 sql 关键字保持小写,并将所有变化(因此“更有趣”)的内容(如表名或列名)放在大写。 这里的代码可能看起来有点“膨胀”,但是如果您有比本例更长的名称(包括模式等)的复杂查询,那么它将提高可读性。 和: 缩进所有对象根据他们的“水平”。

这是我的看法:

select column1, column2
from table1
where (column3 in (
select top(1) column4
from table2
inner join table3
on (table2.column1 = table3.column1)
))
;
  • 所有的都是小写字母,因为它更容易阅读小写字符(我们有代码突出显示来强调关键字) ,也更容易输入
  • 关键字上的每个限制或选项(如选择上的 from 或连接上的 on)都缩进以显示它们对向外关键字的依赖性
  • 结束括号的缩进级别与其中的开始位置相同
  • 在 where 和 on 子句中使用括号可以提高可读性
  • 让分号在同一缩进处关闭 select 语句,这样可以更好地区分多个语句(如果您的语言中需要分号,如 SAS PROC SQL)
  • 它仍然相当紧凑,并没有延伸整个页面