你遵循哪种SQL编码规范?

54

是否有广泛使用的SQL编码标准? SQL与C/C ++类型的编程语言略有不同。真的不知道如何最好地格式化以提高可读性。


同样的问题在几个小时前已经被问到了这里。所以,我不认为将其标记为重复问题是正确的,我只是留下一条通知。 - Frédéric
请参阅以下链接获取SQL格式化程序/代码检查工具:https://docs.sqlfluff.com/en/stable/ | https://github.com/sqlfluff/sqlfluff#the-sql-linter-for-humans - JayRizzo
如果你正在寻找一个SQL格式化程序/代码检查工具,可以参考以下链接:https://docs.sqlfluff.com/en/stable/ | https://github.com/sqlfluff/sqlfluff#the-sql-linter-for-humans。 - undefined
13个回答

59

不会称之为编码标准,更像是编码风格。

SELECT
    T1.col1,
    T1.col2,
    T2.col3
FROM
    table1 T1
    INNER JOIN ON Table2 T2 ON T1.ID = T2.ID
WHERE
    T1.col1 = 'xxx'
    AND T2.Col3 = 'yyy'
  • 首字母大写保留单词
  • 主要关键字换行
  • 不习惯在列前使用逗号
  • 总是使用短而有意义的表别名
  • 视图名称以v为前缀
  • 存储过程名称以sp为前缀(但不要使用“sp_”,因为该前缀被保留用于内置过程)
  • 不要给表加前缀
  • 表名应为单数形式

2
请确保在“sp”后面不要加下划线:http://www.sqlmag.com/Articles/ArticleID/23011/23011.html?Ad=1。我相信你已经知道这一点……这主要是针对那些可能会调整你的风格的人。 - Tadmas
8
个人而言,我更倾向于不在对象名称前加前缀。我认为在没有前缀的情况下阅读起来更加容易和清晰,而且当我使用一个对象时,我应该已经知道它是什么类型的对象(任何阅读我的代码的人也应该如此)。 - Tom H
嗨,如需了解SQL编码标准的更多细节,请查看以下链接:http://selectinsql.blogspot.in/2012/08/sql-server-stored-procedure-coding.html - vijay

16

我喜欢逗号在前的方式:

SELECT
      column1
    , column2
    , column3
    , COALESCE(column4,'foo') column4
FROM
    tablename
WHERE
    column1 = 'bar'
ORDER BY 
      column1
    , column2

依我看,这使得代码最易于阅读和调试。


32
我认为那种风格很让人烦,但这只是个人喜好吧。 - Jonathan Leffler
4
这也使您能够评论单行,而无需担心逗号。 - Domchi
33
除非你需要评论第一行,否则在行尾使用逗号可以让你对任何一行进行评论,除了最后一行。这和在最后一行进行评论是一样的。 - Tom H
11
如果在逗号之前缺少逗号,你会注意到更大的差异,这是显而易见的。它会很明显地突出来。 - Ryan Guill
1
只有在选择列表中没有表达式需要分成多行的情况下,缺少前置逗号才会显眼,例如CASE语句。 - brianary

16
我知道这篇文章很长,但请耐心阅读,它很重要。这个问题引发了一个有趣的讨论。如果你不喜欢数据库块,请继续阅读。
在任何人想要否定我的回答之前,请看一下以下文章以及与之相关的文章,了解锁定和重新编译的内容;这是对SQL数据库最具破坏性的两种资源打击之一。

http://support.microsoft.com/kb/263889

我可以相当快地打字,但是下面的要点我非常严格地遵循,即使这样会更多地输入。事实上,我已经构建了自己的SP应用程序来为我完成这些工作。所以这些要点非常重要!你甚至可能会对自己说,“你在开玩笑吧,这不是问题”,那么你肯定没有阅读上面的文章。而且,微软将这些要点作为注释放入其中,完全是愚蠢的。对我来说,这些问题应该是粗体和大声呼喊的。此外,我还编写了许多代码,使用C#应用程序构建基本脚本,以加快开发速度,并使脚本编写更加容易和快速。虽然还有其他要点,但这就是我在前60%的时间里做的事情。

最佳实践

  • 使用括号将对象括起来,以便查询引擎在遇到字段时明确知道它是什么
  • 与表对象名称和字段名称使用相同的大小写
  • 当从应用程序调用存储过程时,使用带有正确所有者和大小写的完整限定名 [dbo].[procName]。不开玩笑!请阅读上面的文章!
  • 引用对象的所有者,以便明确知道安全性而无需计算
  • 不要使用"sp_",因为这指的是系统存储过程,并具有开销
  • 使用 SET NOCOUNT ON 和 SET NOCOUNT OFF 来消除额外的开销,以跟踪更新了多少条记录在存储过程中,除非你需要它们。通常情况下,你不需要它们,你可以获得巨大的性能提升。

首选项

  • 将存储过程前缀与 proc
  • 在每个存储过程后缀 SEL、UPD、DEL、INS(或 SELECT、UPDATE、DELETE、INSERT)
  • 将保留字大写
  • 将主关键字放在新行上(脚本编写)
  • 在列之前使用逗号(脚本编写)
  • 将视图前缀与 vw
  • 不要为表添加前缀
  • 表名单数形式
  • 为标准名称添加后缀,例如"_ByPK"、"_OrderByLastName"或"_Top15Orders",以获取库存 SP 的变体

选择
CREATE PROC [dbo].[procTable_SEL]
AS
SET NOCOUNT ON
SELECT
    [Column1] = T1.[col1]
  , [Column2] = T1.[col2]
  , [Column3] = T2.[col3]
FROM [dbo].[Table] T1    
INNER JOIN ON [dbo].[Table2] T2 ON T1.ID = T2.ID
WHERE
      T1.[col1] = 'xxx'
  AND T2.[Col3] = 'yyy'
SET NOCOUNT OFF
GO

更新
CREATE PROC [dbo].[procTable_UPD]
AS
SET NOCOUNT ON
UPDATE t1 SET
    [Column1] = @Value1
  , [Column2] = @Value2
  , [Column3] = @Value3
FROM [dbo].[Table1] T1
INNER JOIN ON [dbo].[Table2] T2 ON T1.[ID] = T2.[ID]
WHERE
      T1.[col1] = 'xxx'
  AND T2.[Col3] = 'yyy'
SET NOCOUNT OFF
GO

插入

CREATE PROC [dbo].[procTable_INS]
AS
SET NOCOUNT ON
INSERT INTO [Table1] (
[Column1]
  , [Column2]
  , [Column3]
)
VALUES (
    @Value1
  , @Value2
  , @Value3
)
SET NOCOUNT OFF
GO

或者

CREATE PROC dbo.procTable_INS
AS
SET NOCOUNT ON
INSERT INTO [table1] (
    [Column1]
  , [Column2]
  , [Column3]
)
SELECT
    [Column1] = T1.col1
  , [Column2] = T1.col2
  , [Column3] = T2.col3
FROM dbo.Table1 T1    
INNER JOIN ON Table2 T2 ON T1.ID = T2.ID
WHERE
      T1.[col1] = 'xxx'
  AND T2.[Col3] = 'yyy'
SET NOCOUNT OFF
GO

删除

CREATE PROC dbo.procTable_DEL
AS
SET NOCOUNT ON
DELETE
FROM [dbo].[Table1] T1
INNER JOIN ON [dbo].[Table2] T2 ON T1.[ID] = T2.[ID]
WHERE
      T1.[col1] = 'xxx'
  AND T2.[Col3] = 'yyy'
SET NOCOUNT OFF
GO

7

16
谷歌把我带到了这里... - Kevin Wiskia

4

以下是关于PostgreSQL的非常好的博客,但这个主题适用于一般情况:

可维护的查询 - 我的观点 (depesz.com)

...我决定写可维护查询的优先事项:

  1. 避免无用的输入。

  2. 为表/视图使用别名。总是使用有意义的别名。

  3. 以某种方式缩进代码。

  4. 避免引号(是的,这就是为什么我讨厌Django)。

  5. 使用连接语法。

我同意保留保留字和其他标识符的大写形式,除了我的自己。


总体而言,我发现很多人过于追求 #1(指代码简洁) 。如果为了让我的代码更易读,我宁愿多打几个按键。例如,研究表明使用下划线(而非驼峰命名法)可以大大提高可读性,但是每个人都抱怨这些额外的按键。 - Tom H
没错。下划线是提高标识符可读性的好方法,但是,一如既往,这是一个平衡问题。 - Alex. S.
除了别名之外,我赞同所有内容。SqlServer 2008现在已经具备智能感知功能,我宁愿不因为某个人使用了“Lookup AS L1”这样的语句而在JOIN子句上出错,因此不得不寻找L12代表的含义。我更喜欢这样的写法:Lookup AS Lookup_Foo。 - Kenny Mann

4
我个人不喜欢在存储过程名称前加上sp_,我认为这是多余的。相反,我喜欢使用“功能单元”标识符作为前缀。例如,我会称呼处理订单的存储过程为order_Save、order_GetById、order_GetByCustomer等。这样可以将它们在管理工具中逻辑地分组,并且更难选择错误的存储过程(如GetOrderByProduct、GetCustomerById等)。
当然,这只是我的个人偏好。其他人可能更喜欢将所有的Get存储过程放在一起,所有的Save存储过程放在一起等等。
以上仅供参考。

2
使用“sp_”作为前缀是可能的,但实际上违反了数据库编码标准,因为它被用于将存储过程声明为系统存储过程,从而增加了额外的开销。 - SnapJag
我对前缀的看法是sp_或usp_或其他类似的前缀是多余的,因为我已经知道这些是存储过程。例如,我不会将表格命名为tab_Orders,那么为什么要在存储过程中这样做呢? - ZombieSheep

3

我通常每行只保留很少的内容,例如:

select
    col1,
    col2,
    col3
from
    some_table tabl1
where
    col1 = 'some'
and 
(
    col2 = 'condition'
or  col2 = 'other'
)

把and块与col1='some'对齐在同一列上,这样不是更好吗? - linello

2

谷歌搜索SQL漂亮打印机或者查看这里。我自己没有尝试过,但这可以给你一个好的起点。大多数商业工具像Toad都有一个“格式化”选项来帮助你。


2

2
SELECT c.id
     , c.name
     , c.folder
     , cs.num_users active_members
     , cs.num_videos

  FROM campaign c
  JOIN campaign_stats cs
    ON cs.campaign_id = c.id
  JOIN (SELECT _c.id
             , _c.name

          FROM campaign _c
         WHERE _c.type = 9) t_c 
    ON t_c.id = c.id

 WHERE c.id IN (1,2,3)
   AND cs.num_videos > 10

这对我们来说效果相当不错。

实际上,这个查询并没有太多意义,因为我只是试图快速建立一个示例...但这不是重点。

  • t_c stands for category table sub-query or "temp category".
  • _underscoring of stuff inside sub-queries.
  • alias column names to make sense in the context of the query. e.g. "active_members"
  • putting commas at the beginning of the new lines makes it easier to build dynamic queries:

    $sql .= ", c.another_column"
    
  • everything else is straightforward.


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接