WAWACRM

基于.NET的开源CRM项目
做一件事,一定要坚持。意志不坚定的,参加也没意义。

导航

[WIND] T-SQL 编码标准---抛砖引玉,供大家讨论

Posted on 2005-09-12 08:21  WAWACRM  阅读(477)  评论(3编辑  收藏  举报
 

T-SQL 编码标准

发布日期: 4/15/2005 | 更新日期: 4/15/2005

Brian Walker

可能让人觉得很奇怪,但好像的确没有什么正式的”T-SQL 编码标准。早在 1999 年末的时候,我惊喜地发现 John Hindmarsh 提出的 SQL Server 7.0 标准,我在 2000 2 月的社论中对他的某些建议进行了总结。(2000 2 月以及本月的下载中都包括了 John 原来的标准。)后来,Ron Talmage 撰写了一系列专栏文章,提出了他对各种最佳方法的建议,当然,SQL Server 小组也已正式发布了 SQL Server 最佳方法分析器 (SQLBPA)。现在,一位具有超过 25 年经验的数据库管理员和应用程序开发员 Brian Walker 又提出了他的建议和提示。

进行 T-SQL 编程时常常会忽略编码标准,但这些标准却是开发小组顺利开展工作的关键工具。这里介绍的编码标准是我多年的开发成果。它们当然还没有得到普遍接受,而且不可否认,有些标准带有主观色彩。我的目的实际上更多的是为了提高大家的意识,而不是吹捧自己是 T-SQL 样式方面的仲裁者:最重要的是要建立某些合理的编码标准并遵循这些标准。您在这篇文章中会发现有关 T-SQL 编程的一系列不同的编码标准、技巧和提示。它们并未以任何特定的优先级或重要性顺序列出。

让我们从格式开始。表面上,T-SQL 代码的格式似乎并不重要,但一致的格式可以使您的同事(不论是同一小组的成员还是更大范围的 T-SQL 开发团队的成员)更轻松地浏览和理解您的代码。T-SQL 语句有一个结构,遵循一目了然的结构使您可以更轻松地查找和确认语句的不同部分。统一的格式还使您可以更轻松地在复杂 T-SQL 语句中增删代码段,使调试工作变得更容易。下面是 SELECT 语句的格式示例:

       SELECT C.Name

, E.NameLast

, E.NameFirst

, E.Number

, ISNULL(I.Description,'NA') AS Description

FROM tblCompany AS C

JOIN tblEmployee AS E

ON C.CompanyID = E.CompanyID

LEFT JOIN tblCoverage AS V

ON E.EmployeeID = V.EmployeeID

LEFT JOIN tblInsurance AS I

ON V.InsuranceID = I.InsuranceID

WHERE C.Name LIKE @Name

AND V.CreateDate > CONVERT(smalldatetime,

          '01/01/2000')

ORDER BY C.Name

, E.NameLast

, E.NameFirst

, E.Number

, ISNULL(I.Description,'NA')

 

SELECT @Retain = @@ERROR, @Rows = @@ROWCOUNT

 

IF @Status = 0 SET @Status = @Retain

一个嵌套代码块中的语句使用四个空格的缩进。(上述代码中的多行 SELECT 语句是一个 SQL 语句。)在同一语句中开始新行时,使 SQL 关键字右对齐。将代码编辑器配置为使用空格,而不是使用制表符。这样,不管使用何种程序查看代码,格式都是一致的。

大写所有的 T-SQL 关键字,包括 T-SQL 函数。变量名称及光标名称使用混和大小写。数据类型使用小写。

表名别名要简短,但意义要尽量明确。通常,使用大写的表名作为别名,使用 AS 关键字指定表或字段的别名。

当一个 T-SQL 语句中涉及到多个表时,始终使用表名别名来限定字段名。这使其他人阅读起来更清楚,避免了含义模糊的引用。

当相关数字出现在连续的代码行中时(例如一系列 SUBSTRING 函数调用),将它们排成列。这样容易浏览数字列表。

使用一个(而不是两个)空行分隔 T-SQL 代码的逻辑块,只要需要就可以使用。

声明 T-SQL 局部变量(例如 @lngTableID)时,使用适当的数据类型声明和一致的大写。

始终指定字符数据类型的长度,并确保允许用户可能需要的最大字符数,因为超出最大长度的字符会丢失。

始终指定十进制数据类型的精度和范围,否则,将默认为未指定精度和整数范围。

使用错误处理程序,但要记住行首 (BOL) 中的错误检查示例不会象介绍的那样起作用。用来检查 @@ERROR 系统函数的 T-SQL 语句 (IF) 实际上在进程中清除了 @@ERROR 值,无法再捕获除零之外的任何值。(即使示例起作用,它们也只能捕获最后发生的一个错误,而不是您更想捕获的第一个错误。)必须使用 SET SELECT 立即捕获错误代码,如前面示例所示。如果状态变量仍然为零,应转换到状态变量。

避免使用未声明的功能,例如系统表中未声明的列、T-SQL 语句中未声明的功能或者未声明的系统存储过程或扩展的存储过程。

不要依赖任何隐式的数据类型转换。例如,不能为数字变量赋予字符值,而假定 T-SQL 会进行必要的转换。相反,在为变量赋值或比较值之前,应使用适当的 CONVERT 函数使数据类型相匹配。另一个示例:虽然 T-SQL 会在进行比较之前对字符表达式进行隐式且自动的 RTRIM,但不能依赖此行为,因为兼容性级别设置非字符表达式会使情况复杂化。

不要将空的变量值直接与比较运算符(符号)比较。如果变量可能为空,应使用 IS NULL IS NOT NULL 进行比较,或者使用 ISNULL 函数。

不要使用 STR 函数进行舍入,此函数只能用于整数。如果需要十进制值的字符串形式,应先使用 CONVERT 函数(转至不同的范围)或 ROUND 函数,然后将其转换为字符串。也可以使用 CEILING FLOOR 函数。

使用数学公式时要小心,因为 T-SQL 可能会将表达式强制理解为一个不需要的数据类型。如果需要十进制结果,应在整数常量后加点和零 (.0)

决不要依赖 SELECT 语句会按任何特定顺序返回行,除非在 ORDER BY 子句中指定了顺序。

通常,应将 ORDER BY 子句与 SELECT 语句一起使用。可预知的顺序(即使不是最方便的)比不可预知的顺序强,尤其是在开发或调试过程中。(部署到生产环境中之前,可能需要删除 ORDER BY 子句。)在返回行的顺序无关紧要的情况下,可以忽略 ORDER BY 的开销。

不要在 T-SQL 代码中使用双引号。应为字符常量使用单引号。如果没有必要限定对象名称,可以使用(非 ANSI SQL 标准)括号将名称括起来。

SQL Server 2000 中,尽量使用表变量来代替临时表。如果表变量包含大量数据,请注意索引非常有限(只有主键索引)。

先在例程中创建临时表,最后再显式删除临时表。将 DDL DML 语句混合使用有助于处理额外的重新编译活动。

要认识到临时表并不是不可使用,适当地使用它们可以使某些例程更有效,例如,当需要重复引用大型表或常用表中的某个数据集时。但是,对于一次性事件,最好使用导出表。

使用表值 UDF 时要小心,因为在变量(而不是常量)中传递某个参数时,如果在 WHERE 子句中使用该参数,会导致表扫描。还要避免在一个查询中多次使用相同的表值 UDF。但是,表值 UDF 确实具有某些非常方便的动态编译功能。[相关资料:参阅 Tom Moreau 2003 11 月份生成序列号专栏中的使用 UDF 填充表变量。-编者按]

几乎所有的存储过程都应在开始时设置 SET NOCOUNT ON,而在结束时设置 SET NOCOUNT OFF[SET NOCOUNT ON 使 SQL Server 无需在执行存储过程的每个语句后向客户端发送 DONE_IN_PROC 消息。- 编者按] 此标准同样适用于触发器。

只要在例程中使用多个数据库修改语句,包括在一个循环中多次执行一个语句,就应考虑声明显式事务。

使用基于光标的方法或临时表方法之前,应先寻找基于集的解决方案来解决问题。基于集的方法通常更有效。

与临时表一样,光标并不是不可使用。对小型数据集使用 FAST_FORWARD 光标通常要优于其他逐行处理方法,尤其是在必须引用几个表才能获得所需的数据时。在结果集中包括合计的例程通常要比使用光标执行的速度快。如果开发时间允许,基于光标的方法和基于集的方法都可以尝试一下,看哪一种方法的效果更好。

使用包含序号(从 1 N)的表很方便。

理解 CROSS JOIN 的工作原理并加以利用。例如,您可以在工作数据表和序号表之间有效地使用 CROSS JOIN,结果集中将包含每个工作数据与序号组合的记录。

我的结束语是:T-SQL 代码往往很简洁,因此如果某个代码块看起来很难处理或重复内容较多,那么可能存在一种更简单,更好的方法。

结论

如果您对我的建议有任何看法,欢迎随时向我发送电子邮件进行讨论,也可以就其他问题提出您的建议。我希望您将此作为谈话的开场白。

其他信息:摘自 Karen 2000 2 月份的社论

在标准开发的前沿阵地上,有一股以 SQL Server 数据库管理员 John Hindmarsh 为首的独立的新生力量。MCTMCSE MCDBA 都是最值得您花时间去研究的。John 的贡献是撰写了一份详细的白皮书,概述了他对各种 SQL Server 相关标准提出的建议。我所知道的其他唯一提出类似建议的文章是 Andrew Zanevsky 的《Transact-SQL Programming(ISBN 1-56592-401-0) 中的“Format and Style”一章。AndrewSQL Server Professional 的投稿人 Tom Moreau Paul Munkenbeck 以及 John 的朋友兼同事 Stephen James 都为 John 的白皮书做出过贡献。下面是 John 为编写存储过程提供的建议示例:

使用 SQL-92 标准连接句法。

为了提高性能,应优先使用连接,然后使用子查询或嵌套查询。

确保变量和参数的类型和大小与表数据列相匹配。

确保使用所有变量和参数,或者全部删除。

尽可能将临时对象放置在本地。

只使用在存储过程中创建的临时表。

检查输入参数的有效性。

优先使用 SELECT...INTO,然后使用 INSERT...SELECT,以避免大量死锁。

维护工作需要的逻辑单元;在可以缩短的情况下,不要创建大量或长时间运行的进程。

不要在任何代码中使用 SELECT *

在过程中使用缩进、块、制表符和空格(参阅示例脚本)。

T-SQL 语句要大写。

在过程中添加大量注释,确保可以识别进程。在有助于澄清处理步骤的地方使用行注释。

包括事务管理,除非要从 MTS 进程中调用过程。(为 MTS 进程编写独立的过程。)

监视 @@TRANCOUNT 以确定事务的责任级别。

避免使用 GOTO,错误处理程序中除外。

避免使用嵌套过程。

避免隐式解析对象名称,确保所有对象都归 dbo 所有。

下载 412BRIAN.ZIP

链接至www.microsoft.com/downloads/details.aspx?displayla%20ng=en&familyid=B352EB1F-D3CA-44EE-893E-9E07339C1F22&displaylang=en

有关 SQL Server Professional Pinnacle Publishing 的详细信息,请访问其 Web 站点 http://www.pinpub.com/

注意:这不是 Microsoft Corporation Web 站点。Microsoft 对该 Web 站点上的内容不承担任何责任。

本文转载自 2004 12 月份的 SQL Server Professional。除非另行说明,否则版权所有 2004 Pinnacle Publishing, Inc.。保留所有权利。SQL Server Professional Pinnacle Publishing 独立发行的刊物。未经 Pinnacle Publishing, Inc. 事先同意,不得以任何方式使用或复制本文的任何部分(评论文章中的简短引用除外)。如需与 Pinnacle Publishing, Inc. 联系,请拨打 1-800-788-1900