1. 变量/函数/存储过程的命名(Variable/UDF/Stored Procedure Naming)
2. T-SQL 编码标准
· 一个嵌套代码块中的语句使用四个空格的缩进。(上述代码中的多行 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)。
· 不要在 T-SQL 代码中使用双引号。应为字符常量使用单引号。如果没有必要限定对象名称,可以使用(非 ANSI SQL 标准)括号将名称括起来。
Header Sample Comments
/*****************************************************************
** File: usp_InsertEquipments.sql
** Name: usp_InsertEquipments
** Desc: Insert new equipment number and type in equipment table
**
** Return Values: ErrorCode1: Descr
** ErrorCode2: Descr
**
** Call by: Application Module Name
**
** Parameters:
** Input Output
** ------------ --------------
** @inPara1 @outPara1
** @inPara2
**
** Auth:
** Date:
** ****************************************************************
** Date Author Description
** --------- ------------- ------------------
** 2006-3-31 Jack Fixed: 49 Error handing
*******************************************************************/
数据流程控制的范例
/*******************************************************
** Process description
********************************************************/
Begin
Insert Order (OrderDate, RequestedById,
TargetDate, DestinationLocation)
Values (@OrderDate, @ContractId,
@TargetDate, @LocId)
Set @ErrorCode=@@error
If @ErrorCode<>0
Begin
RaiseError (‘Error occurred while inserting Order!’,16,1)
Return @ErrorCode
End
End
3. 变量
4. T-SQL脚本优化技巧
--NOT EXISTS, 效率最高
SELECT a.hdr_key
FROM hdr_tbl a
WHERE NOT EXISTS (SELECT * FROM dtl_tbl b WHERE a.hdr_key = b.hdr_key)
--LEFT JOIN
SELECT a.hdr_key
FROM hdr_tbl a
LEFT JOIN dtl_tbl b ON a.hdr_key = b.hdr_key
WHERE b.hdr_key IS NULL
--NOT IN ,效率最低
SELECT hdr_key
FROM hdr_tbl
WHERE hdr_key NOT IN (SELECT hdr_key FROM dtl_tbl)
--不好的写法:
IF (SELECT COUNT(*) FROM table_name WHERE column_name = 'xxx')
--正确的写法:
IF EXISTS (SELECT * FROM table_name WHERE column_name = 'xxx')
--可能不好的写法:
SELECT * FROM tblTaskProcesses
WHERE nextprocess = 1
AND processid IN (8,32,45)
--正确的写法:
SELECT * FROM tblTaskProcesses (INDEX = IX_ProcessID)
WHERE nextprocess = 1
AND processid IN (8,32,45)
--不好的写法:
WHERE SUBSTRING(firstname,1,1) = 'm'
--正确的写法:
WHERE firstname like 'm%'
--不好的写法:
SELECT member_number, first_name, last_name
FROM members
WHERE DATEDIFF(yy,datofbirth,GETDATE()) > 21
-- 正确的写法:
SELECT member_number, first_name, last_name
FROM members
WHERE dateofbirth < DATEADD(yy,-21,GETDATE())
--不好的写法:
WHERE NOT column_name > 5
--正确的写法:
WHERE column_name <= 5
--正确的写法:
SELECT *
FROM Northwind.dbo.Orders
WHERE OrderDate > ' 12/31/1997 '
--不好的写法:
SELECT *
FROM Northwind.dbo.Orders
WHERE OrderDate > ' 12/31/97 '
5. 存储过程的开发和优化技巧
--与临时表一样,光标并不是不可使用。对小型数据集使用FAST_FORWARD 光标通常要优于其他逐行处理方法,尤其是在必须引用几个表才能获得所需的数据时。在结果集中包括“合计”的例程通常要比使用光标执行的速度快。如果开发时 间允许,基于光标的方法和基于集的方法都可以尝试一下,看哪一种方法的效果更好.
--使用表值 UDF 时要小心,因为在变量(而不是常量)中传递某个参数时,如果在 WHERE 子句中使用该参数,会导致表扫描。还要避免在一个查询中多次使用相同的表值 UDF。但是,表值 UDF 确实具有某些非常方便的动态编译功能
--不好的写法:
Create procedure proc_1
As
Begin
Begin transaction
-- step 1 verify the data
-- step 2 perform calculations
-- step 3 get default variable values (date, user info)
-- update/insert records
commit
end
--不好的写法:
Create procedure proc_1
As
Begin
-- step 1 verify the data
-- step 2 make calculations
-- step 3 get default variable values (date, user info)
Begin transaction
-- update/insert records
commit
end
6. 补充说明