图片 25

《SQL Server 2008从入门到精通》–20180710

目录

摘要 本文是参考相关资料总结的一篇关于T-SQL语言编程规范的文章,旨在为需要这方面资料的IT公司设计开发人员提供一个参考。
来源:http://blog.csdn.net/zhzuo

概述

1.使用Transact-SQL语言编程

尽管SQL Server
2008提供了图形化界面,但只有一种Transact-SQL语言能够直接与数据库引擎进行交互。根据执行功能特点可以将Transact-SQL语言分成3大类:数据定义语言DDL,数据操纵语言DML,数据控制语言DCL。

1.1.基本原则

以大小写敏感编写SQL语句。

尽量使用Unicode
数据类型。

优先使用连接代替子查询或嵌套查询。

尽量使用参数化SQL查询代替语句拼接SQL查询。

禁止使用[拼音]+[英语]的方式来命名SQL对象或变量。

尽量使用存储过程代替SQL语句。

1.1.数据定义语言DDL

是最基础的Transact-SQL语言类型,用来创建数据库和创建,修改,删除数据库中的各种对象,为其他语言的操作提供对象。例如数据库,表,触发器,存储过程,视图,函数,索引,类型及用户等都是数据库中的对象。常见的DDL语句包括

CREATE TABLE--创建表
DROP TABLE--删除表
ALTER TABLE--修改表

1.2.基本规范

建议采用Pascal样式或Camel样式命名数据库对象。

大写T-SQL语言的所有关键字,谓词和系统函数。

1.2.数据操纵语言DML

是用于操纵表和视图中的数据的语句,例如查询数据(SELECT),插入数据(INSERT),更新数据(UPDATE)和删除数据(DELETE)等。

命名规范

在一般情况下,采用Pascal样式或Camel样式命名数据库对象,使在开发基于数据库应用程序的时候通过ORM工具生成的数据访问代码不需要调整就符合程序开发语言(比如C#)命名规范。另外,关系型数据库同Xml结合得越来越紧密,规范的命名越来越重要。

在实际数据库开发过程中,如果需求方已经提供数据库设计方案,建议以提供的方案为准;在原有数据库上进行升级开发时,在可行的情况下可适当做出设计调整以符合编程规范。

1.3.数据控制语言DCL

涉及到权限管理的语言称为数据控制语言,主要用于执行有关安全管理的操作。如授予权限(GRANT),收回权限(REVOKE),拒绝授予主体权限,并防止主体通过组或角色成员继承权限(DENY

1.3.对象命名

1.4.Transact-SQL语言基础

1.3.1. 数据库

第一种方式,采用Pascal样式命名,命名格式为[项目英文名称]。

示例:AdventureWorks

第二种方式,采用Pascal样式命名,命名格式为[项目英文名称]

  • Db。

示例:AdventureWorksDb

 
BizTalkRuleEngineDb

建议采用第一种方式。

1.4.1.常量与变量

常量不多说。在SQL Server
2008中,存在两种变量。一种是系统定义和维护的全局变量,一种是用户定义用来保存中间结果的局部变量。

1.3.2. 数据库文件

数据文件:[数据库名称] +
_Data.mdf

日志文件:[数据库名称] +
_Log.ldf

示例:AdventureWorks_Data.mdf

     
AdventureWorks_Log.ldf

1.4.1.1.系统全局变量

系统全局变量分为两大类,一类是与当然SQL
Server连接或与当前处理有关的全局变量,如@@Rowcount表示最近一个语句影响的行数。@@error表示保存最近执行操作的错误状态。一类是与整个SQL
Server系统有关的全局变量,如@@Version表示当前SQL Server的版本信息。

SELECT @@VERSION AS 当前版本;--查看当前SQL Server的版本信息

结果如图所示
图片 1

1.3.3. 关系型数据仓库

采用Pascal样式命名,命名格式为[项目英文名称]

  • DW。

示例:AdventureWorksDW

1.4.1.2.局部变量

局部变量能够拥有特定数据类型,有一定的作用域,一般用于充当计数器计算或控制循环执行次数,或者用于保存数据值。局部变量前只有1个@符,用DECLARE语句声明局部变量。

USE test
DECLARE @StudentId varchar(20)
SET @StudentId=(
SELECT Student.stu_no
FROM Student
WHERE stu_enter_score='603')
SELECT @StudentId AS 入学分数为603的学生学号
GO

结果如图所示
图片 2

1.3.4. 数据架构

除SQL Server
系统定义的数据架构外,新建架构采用Pascal样式命名,命名格式为[架构名]。

示例:HumanResources

      Production

对数据库对象
Table,View,Procedure,Function等使用数据架构进行归类。在SQL Server
2000中dbo为默认架构。

2.运算符

1.3.5. 数据表

采用Pascal样式命名,命名格式为[表名]。

示例:Employee

      Product

表名以英文单数命名,主要是参考SQL
Server
2005示例数据库,个人理解不采用复数是为了更好的使用ORM工具生成符合编程规范的代码(比如C#)。

示例:使用Product

 而不是Products

2.1.算数运算符

在SQL Server
2008中,算数运算包括加(+)减(-)乘(*)除(/)取模(%)。举一个简单的例子。
示例1:在Student表中添加一列,列名为stu_age,根据Student表的stu_birthday列计算stu_age列并插入数据。(演示插入整列数据的方法)
Student表数据如图所示
图片 3
执行下面的语句

ALTER TABLE Student
ADD stu_age int;--在Student表中添加stu_age列
CREATE TABLE #agetemp(stu_no varchar(8),age int);--新建一个临时表
INSERT INTO #agetemp(stu_no,age)--在临时表中插入学号和计算出来的年龄
SELECT Student.stu_no,YEAR(GETDATE())-YEAR(stu_birthday)--利用函数和运算符计算年龄
FROM Student;
UPDATE Student
SET Student.stu_age=#agetemp.age--将临时表中的age列数据整个复制到Student表的stu_age列
FROM #agetemp
WHERE Student.stu_no=#agetemp.stu_no--条件是两个表的stu_no列值相等
GO
SELECT * FROM Student

结果如图所示
图片 4

1.3.6. 数据视图

视图名称采用Pascal样式命名,命名格式为v

  • [视图名称]。

示例:vEmployee

     
vSalesPerson

2.2.赋值运算符

即等号(=),将表达式的值赋予另一个变量。举一个简单的例子。
示例2:计算Student表中学生的平均入学成绩并打印。
Student表的数据如图所示,stu_enter_score列存放了学生的入学成绩
图片 5
执行下面的语句

DECLARE @average int--声明@average变量
SET @average=(--将计算出的平均值赋值给@average
SELECT AVG(stu_enter_score)
FROM Student)
PRINT @average--打印@average的值

结果如图所示
图片 6

1.3.7. 数据列

列名称命名采用英文单词或缩写,英文单词只来自于具体业务定义,尽量表达清楚含义。采用Pascal样式命名,命名格式为[列名称]。

示例:AddressID

      PostalCode

尽量避免使用拼音命名,如果不可避免,对于比较短的列名,采用拼音全写,如果拼音列名比较复杂,可以采用首个字用全拼,其它字用首字母大写表示。

示例:宁波
Ningbo

  经营方式 JingYFS

2.3.位运算符

位运算符包括与运算(&),或运算(|)和异或运算(^),可以对两个表达式进行位操作,这两个表达式可以是整型数据或二进制数据。Transact-SQL首先把整型数据转换为二进制数据,然后按位运算。举个简单的例子。
示例3:声明2个int型变量@num1,@num2,对这两个赋值且做与或异或运算。
执行下面的语句

DECLARE @num1 int,@num2 int
SET @num1=5 
SET @num2=6
SELECT @num1&@num2 AS 与,
@num1|@num2 AS 或,
@num1^@num2 AS 异或

结果如图所示
图片 7
扩展示例4:写一个十进制转换为二进制的函数

CREATE FUNCTION Bin_con_dec(@dec int)--定义十进制转换为二进制函数
RETURNS varchar(20)
AS
BEGIN
DECLARE @quo int,@remainder varchar(20),@quo1 int
SET @quo=@dec
SET @remainder=''
WHILE @quo<>0
BEGIN
SET @quo1=@quo/2
SET @remainder=CAST(@quo%2 AS varchar(20))+@remainder
SET @quo=@quo1
END
RETURN @remainder
END

执行上面的函数后,运行下列语句验证函数正确性

PRINT dbo.Bin_con_dec(42)

结果为101010,函数定义正确。

1.3.8. 存储过程

建议采用Pascal样式命名,命名格式为[存储过程名称]。

示例:GetUser

     AddUser

备注:在SQL Server
2005示例数据库中使用Camel样式命名。

2.4.比较运算符

也称关系运算符,用于比较两个值的关系,常见的有等于(=),大于(>),小于(<),大于等于(>=),小于等于(<=),不等于(<>或!=)
示例5:从Student表中查询入学成绩在平均分以上的学生信息
Student表的数据如图所示
图片 8
执行下列语句

DECLARE @ave int
SET @ave=(SELECT AVG(stu_enter_score) FROM Student)
SELECT *FROM Student
WHERE stu_enter_score>=@ave;

结果如下图所示
图片 9

注:不能直接把代码写成下面的形式

SELECT * FROM Student
WHERE stu_enter_score>=AVG(stu_enter_score)

消息147,级别15,状态1,第2 行
聚合不应出现在WHERE 子句中,除非该聚合位于HAVING
子句或选择列表所包含的子查询中,并且要对其进行聚合的列是外部引用。

因为AVG是聚合函数。

1.3.9. 函数

自定义函数采用Pascal样式命名,命名格式为[函数名],系统函数使用全部大写。

示例:SELECT ISNULL(@LastName,’Unknown last
name’);

GETDATE()

2.5.逻辑运算符

逻辑运算符的作用是对条件进行测试。ALL,AND,ANY,BETWEEN,EXISTS,IN,LIKE,NOT,ALL,SOME。下面用SOME来举例。SOME的作用是如果在一组比较中,有些为true那就为true。
示例6:查询Student表中是否存在入学成绩高于平均分的学生,如果存在,输出true,不存在输出false。
Student表的stu_enter_score列(入学成绩)数据如图所示
图片 10
执行下面的语句

USE test
IF (SELECT AVG(stu_enter_score) FROM Student)<=SOME(SELECT stu_enter_score FROM Student)
PRINT 'true'
ELSE
PRINT 'false'
GO

结果如图所示
图片 11

1.3.10.     用户定义数据类型

采用Pascal样式命名,命名格式为[自定义数据类型名称]。

示例:Flag

      NameStyle

2.6.连接运算符

加号(+)是字符串连接运算符,可以用它把字符串串连起来,在示例4的十进制转二进制函数中,就用上了加号。
示例7:将Student表的stu_name列和stu_enter_score列放在同一列显示,列名为score
Student表的数据如图所示
图片 12
执行下列语句

SELECT stu_name+CAST(stu_enter_score AS VARCHAR(3)) AS score FROM Student

执行结果如图所示
图片 13

注:stu_enter_score列数据类型为int,加号只对字符串类型数据有效,因此要用CAST函数将stu_enter_score的数据类型转换为varchar(3),这样才能实现字符串拼接。

1.3.11.     DML触发器

DML触发器是当数据库服务器中发生数据操作语言
(DML) 事件时要执行的操作。DML 事件包括对表或视图发出的 UPDATE、INSERT 或
DELETE 语句。根据事件不同命名规则使用前缀进行区分,格式为 [u|i|d] +
[表名|视图名]

示例:uEmployee

  iEmployee

      dEmployee

另外一种方式为,

AFTER 触发器:TR_表名_[后面插入加I,修改加U,删除加D]。

INSTEAD OF 触发器:TR_表名或视图名_OF[后面插入加I,修改加U,删除加D]

2.7.一元运算符

一元运算符只对一个表达式执行操作,该表达式可以是数字数据类型中的任何一种数据类型。SQL
Server 2008提供的一元运算符包含正(+),负(-),位反(~)。
示例8:声明一个int数据类型变量@num并赋值,对该变量做正负位反操作。
执行下列语句

DECLARE @num INT
SET @num=45
SELECT +@num AS 正,-@num AS 负,~@num AS 位反
GO

结果如图所示
图片 14

注:位反操作符用于取一个数的补数,只能用于整数。

1.3.12.     DDL触发器

响应各种数据定义语言
(DDL) 事件而激发。这些事件主要与以关键字 CREATE、ALTER 和 DROP 开头的
Transact-SQL 语句对应。执行 DDL 式操作的系统存储过程也可以激发 DDL
触发器。

采用Camel样式命名,命名单词能够描述DDL触发器功能。

示例:

CREATE TRIGGER safety

ON DATABASE

FOR DROP_TABLE, ALTER_TABLE

AS

   PRINT ‘You must
disable Trigger “safety” to drop or alter tables!’

   ROLLBACK ;

另外一种方式为添加ddl前缀,

示例:

CREATE TRIGGER [ddlDatabaseTriggerLog]

ON DATABASE

FOR DDL_DATABASE_LEVEL_EVENTS

AS

2.8.运算符的优先级

优先级 运算符
1 ~(位反)
2 *(乘),/(除),%(取模)
3 +(正),-(负),+(加),+(连接),-(减),&(位与)
4 =,>,<,>=,<=,<>,!=,!>,!<(比较运算符)
5 ^(位异或),位或(符号打不出来,前面有,自己翻)
6 NOT
7 AND
8 ALL,ANY,BETWEEN,IN,LIKE,ALL,SOME
9 =(赋值)

当表达式中的运算符有相同的优先级时,按照它们在表达式中的位置,一元运算符按从右往左运算,二元运算符(对两个表达式作用的运算符)按从左往右运算。
示例9:验证运算符优先级
执行下列语句

DECLARE @result INT,@num INT
SET @num=45
SET @result=@num+(~@num)*4-@num/(~@num)
SELECT @result AS result
GO

结果如图所示
图片 15
计算代码中的表达式
@result=@num+(~@num)4-@num/(~@num)
=@num+(-46)
4-@num/(-46)
=45+(-46)4-45/(-46)
=45+(-46)
4
=-139

1.3.13.     主键、外键关系和索引

主键:
PK_[表名称]_[主键];如果是组合主键,使用PK_[表名]_[主键1]_[主键2]。

示例:PK_Store_CustomerID

 
PK_StoreContact_CustomerID_ContactID

外键关系:FK_[从表名称]_[主表名称]_[外键列名称]。

示例:FK_StoreContact_Store_CustomerID

聚集索引:PK_[表名称]_[主键];如果是组合主键,使用PK_[表名]_[主键1]_[主键2]。

示例:PK_Store_CustomerID

 
PK_StoreContact_CustomerID_ContactID

唯一非聚集索引:AK_[表名称]_[列名称]。

示例:AK_Store_rowguid

不唯一非聚集索引:PK_[表名称]_[列名称]。

示例:IX_Store_SalesPersonID


XML索引:PXML_[表名称]_[Xml类型列名称]。

示例:PXML_Store_Demographics

备注:以上命名参考Sql
Server 2005示例数据库,一般只需设计器自动生成,不需要额外修改。

3.控制语句

1.4.参数命名

3.1.BEGIN END语句块

BEGIN END可以定义SQL
Server语句块,使这些语句作为一组语句执行,允许语句嵌套。举例请见示例4

1.4.1. 数据列参数

命名格式为 @ +
[列名称]。

示例:@EmployeeID

在列名不符合Pascal样式时(早期遗留系统),例如使用全部大写的列名称,或使用“_”进行连接的字段名称,参数名称定义使用
@ + [列名称],这里的列名称尽量符合Pascal样式命名。

3.2.IF ELSE语句块

用于指定T-SQL语句的执行条件,若条件为真,则执行条件表达式后面的语句,条件为假时,可以试用ELSE关键字指定要执行的T-SQL语句。举例请见示例4

1.4.2. 非数据列参数

在参数无法跟列名称进行关联时,使用能够反映该参数功能的英文单词或单词组合,
采用Pascal样式命名。

示例:@ErrorID

      @Flag

3.3.CASE分支语句

示例10:将Student表的学生,性别和籍贯打印出来,要求籍贯只能显示省内,省外或自治区。
Student表的数据如图所示
图片 16
执行下列语句

SELECT stu_name AS 姓名,stu_sex AS 性别,
(CASE stu_native_place
WHEN '浙江' THEN '省内'
WHEN '内蒙古' THEN '自治区'
WHEN '西藏' THEN '自治区'
WHEN '宁夏' THEN '自治区'
WHEN '新疆' THEN '自治区'
WHEN '广西' THEN '自治区'
ELSE '省外'
END) AS 籍贯 
FROM Student

结果如图所示
图片 17

1.5.常见命名

3.4.WHILE语句

用于设置重复执行T-SQL语句或语句块的条件。
示例11:用“*”在屏幕上输出一个宽度为9的菱形。
执行下列语句

DECLARE @width int,@j int
SET @width=9--@width为菱形的最大宽度
SET @j=1--@j表示每行打印的“*”符号的个数
WHILE @j<=@width
BEGIN
PRINT SPACE((@width-@j)/2)+REPLICATE('*',@j)--SPACE函数打印n个空字符,REPLICATE打印n个特定字符串
SET @j=@j+2
END
SET @j=@width-2
WHILE @j>0
BEGIN
PRINT SPACE((@width-@j)/2)+REPLICATE('*',@j)
SET @j=@j-2
END

结果如图所示
图片 18

1.5.1. 常用字段命名

这里的常用字段是指在建表时频繁使用的表名或列名,下表对常用字段进行建议性定义,

列名称         
数据类型             说明

CreatedDate    
datetime                纪录创建日期,一般使用GETDATE()自动生成

ModifiedDate       
datetime                纪录最后修改日期,首次使用GETDATE()

DeletedDate    
datetime                记录删除(标记删除)日期

StartDate      
datetime                开始日期

EndDate        
datetime                结束日期

StartTime      
datetime                开始时间

EndTime        
datetime                结束时间

rowguid        
uniqueidentifier        唯一标识行的ROWGUIDCOL号,用于支持合并复制

ID             
int                 使用ID代替Id或id。一般为自增长主键列

ParentID           
int                 父ID

Status         
int                 状态

3.5.WAITFOR延迟语句

WAITFOR延迟语句可以让在它之后的语句在一个指定的时刻或是时间间隔后执行,可以悬挂起批处理,存储过程或事务的执行。
示例12:在某个时间点查询Student表学号为20180101的学生信息

BEGIN
WAITFOR TIME '15:03'--在15点03分查询
SELECT * FROM Student
WHERE stu_no='20180101'
END

示例13:在3分钟后查询Student表学号为20180102的学生信息

BEGIN
WAITFOR DELAY '00:03'--在3分钟后查询
SELECT * FROM Student
WHERE stu_no='20180102'
END

图片 19

SQL编写

3.6.RETURN无条件退出语句

该语句表示无条件终止查询,批处理或存储过程的执行。存储过程和批处理RETURN语句后面的语句都不再执行。当在存储过程中使用该语句时,可以指定返回给调用应用程序、批处理或过程的整数值。如果RETURN未指定返回值,则存储过程的返回值是0

3.1.大小写

大写T-SQL
语言的所有关键字,谓词和系统函数。变量名称及游标名称使用Pascal样式。数据类型定义使用全部小写。

示例:DECLARE @LastName nvarchar(32);

3.7.GOTO跳转语句

该语句使T-SQL批处理的执行跳转至指定标签。由于该语句破坏结构化语句的结构,尽量少用
示例13:将GOTO作为分支机制
执行下面语句

DECLARE @Counter int;  
SET @Counter = 1;  
WHILE @Counter < 10  
BEGIN   
    SELECT @Counter  
    SET @Counter = @Counter + 1  
    IF @Counter = 4 GOTO Branch_One --Jumps to the first branch.  
    IF @Counter = 5 GOTO Branch_Two  --This will never execute.  
END  
Branch_One:  
    SELECT 'Jumping To Branch One.'  
    GOTO Branch_Three; --This will prevent Branch_Two from executing.  
Branch_Two:  
    SELECT 'Jumping To Branch Two.'  
Branch_Three:  
SELECT 'Jumping To Branch Three.';

结果如图所示
图片 20
当Counter=4时,执行GOTO语句输出Branch
One,执行完这个语句之后就打破了WHILE循环,接着执行Branch_One语句中的GOTO,输出Branch
Three,结束。

注:在WHILE循环中使用GOTO会打破循环。

示例14:用GOTO语句实现示例11中打印菱形的功能
执行下列语句

DECLARE @width int,@j int,@i int
SET @width=9--@width为菱形的最大宽度
SET @j=1--@j表示每行打印的“*”符号的个数
SET @i=1--@i表示下一行打印第i行
Set3:PRINT SPACE((@width-@j)/2)+REPLICATE('*',@j)--SPACE函数打印n个空字符,REPLICATE打印n个特定字符串
SET @i=@i+1
IF @i<=(@width+1)/2
GOTO Set1
ELSE
GOTO Set2
Set1:
SET @j=@j+2
GOTO Set3
Set2:
SET @j=@j-2
IF @j>=1
GOTO Set3

结果如图所示
图片 21

3.2.使用“;”

使用“;”作为
Transact-SQL
语句终止符。虽然分号不是必需的,但使用它是一种好的习惯。

示例:

USE AdventureWorks;

GO

DECLARE @find varchar(30);

SET @find = ‘Man%’;

SELECT LastName, FirstName,
Phone

FROM Person.Contact

WHERE LastName LIKE @find;

3.8.TRY CATCH错误处理语句

如果TRY块内部发生错误,会将控制传递给CATCH块内的语句组。TRY
CATCH构造捕捉所有严重级别大于10但不会终止数据库连接的错误。
示例15:TRY CATCH的示例
执行下列语句

BEGIN TRY
SELECT * FROM Student
SELECT 120/0 FROM Student
END TRY
BEGIN CATCH
SELECT ERROR_MESSAGE() AS '错误信息'
END CATCH

执行结果如图所示
图片 22
语句中3个select语句全部都执行了。如果把报错的select语句放到正常的select语句前面,正常的select语句还能不能执行呢?执行下列语句

BEGIN TRY
SELECT 120/0 FROM Student
SELECT * FROM Student
END TRY
BEGIN CATCH
SELECT ERROR_MESSAGE() AS '错误信息'
END CATCH

结果如图所示
图片 23
正常select语句无法执行。TRY
CATCH语句的逻辑是,一旦TRY语句块中出现问题语句,立刻跳转到CATCH语句块,TRY语句块接下去的语句不再执行。

3.3.存储格式

尽量采用Unicode数据存储格式,提高可移植性和兼容性,实际应用中尽量使用nchar、nvarchar、ntext代替char、varchar、text。

4.常用函数

3.4.类型选择

如果字符具有明确的长度,使用nchar代替nvarchar;char代替varchar。

在只有两个可能数值时,使用bit代替int或smallint。

在SQL Server
2005中,使用nvarchar(MAX)代替ntext;varchar(MAX)代替text;varbinary(MAX)代替image。

在特殊的数据表结构中可考虑xml数据类型,达到事半工倍的效果。

4.1.数据类型转换函数

默认情况下SQL
Server会对一些数据类型进行自动转换,这种转换称为隐式转换。遇到无法自动转换,则需要用CAST()函数和CONVERT()函数转换,这种转换称为显式转换。CAST()函数和CONVERT()函数的功能是相同的,CAST函数更容易使用,CONVERT函数的优点是可以指定日期和数值格式。
示例16:将Student表中的学号转换为日期格式
下面两句语句的功能是一样的,执行下列语句

SELECT stu_name,CAST(stu_no AS DATE) AS 学号转换成日期,stu_enter_score,stu_birthday FROM Student
SELECT stu_name,CONVERT(DATE,stu_no) AS 学号转换成日期,stu_enter_score,stu_birthday FROM Student

结果如图所示
图片 24
示例17:用CONVERT()函数将stu_birthday转化成指定格式的日期
执行下列语句

SELECT stu_name,CONVERT(VARCHAR(20),stu_birthday,101) FROM Student
--CONVERT函数将DATE类型的stu_birthday字段转化为字符串,并限定了样式,代码101

结果如图所示
图片 25

注:在上述代码中,CONVERT(DATE,stu_birthday,101)这么写是没用的。101格式码只对日期格式转化为字符串有效,其他格式转化为日期格式是无效的。

其他常用函数太简单了这边不写了,略。

3.5.默认值

在建立数据表时,尽量使用默认值代替NULL值。比如设置CreatedDate列默认值为GETDATE()。在可行的情况下设置字段为不允许空。

3.6.字段长度

始终指定字符数据类型的长度,并确保允许用户可能需要的最大字符数,避免超出最大长度时出现字符丢失现象。对于字符型数据,建议采用2的n次方来定义数据长度。

示例:nvarchar(32)

  varchar(64)

3.7.使用“’”

在 T-SQL
代码中为字符常量使用单引号,避免使用双引号。

3.8.语句缩进

一个嵌套代码块中的语句使用四个空格的缩进。使用Microsoft
SQL Server Management Studio
,选择“工具”菜单,打开“选项”菜单,在选项对话框中选择文本编辑器->纯文本->制表符,选中“插入空格单选框”,设置“制表符大小”为4,缩进大小为“4”。

3.9.语句换行

建议SQL代码每行以关键字或“’”开头。

示例:

SELECT [ShiftID]

      ,[Name]

      ,[StartTime]

      ,[EndTime]

      ,[ModifiedDate]

  FROM [AdventureWorks].[HumanResources].[Shift]

3.10.   语句分割

使用一个(而不是两个)空行分隔
T-SQL 代码的逻辑块。

3.11.   使用“*”

尽量避免在任何代码中使用
“SELECT *”。

3.12.   表名别名

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

3.13.   类型转换

不要依赖任何隐式的数据类型转换,不要假定
T-SQL
会进行必要的转换。例如,把数字变量赋予字符值。相反,在为变量赋值或比较值之前,应使用适当的
CONVERT 函数使数据类型相匹配。

3.14.   数值比较

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

3.15.   排序

决不要依赖 SELECT
语句会按任何特定顺序返回行,除非在 ORDER BY 子句中指定了顺序。通常,应将
ORDER BY 子句与 SELECT
语句一起使用。可预知的顺序(即使不是最方便的)比不可预知的顺序强,尤其是在开发或调试过程中。在返回行的顺序无关紧要的情况下,可以忽略
ORDER BY ,减少资源开销。

3.16.   Unicode字符串

在Unicode字符前面使用N前缀,避免引起数据的不一致。

示例:


Assumes the default code page is not Greek

CREATE TABLE #t1 (c1 nchar(1))

INSERT #t1 VALUES(N’Ω’)

INSERT #t1 VALUES(‘Ω’)

SELECT * FROM
#t1

输出结果:

c1  


Ω

O

3.17.   BEGIN…END 块

在SQL代码快中尽量使用BEGIN…END
语句块,提高代码可阅读性。

3.18.   TRY块

在SQL Server
2005中对一些可能执行失败的语句尽量使用TRY块。Transact-SQL
语句组可以包含在 TRY 块中,如果 TRY 块内部发生错误,则会将控制传递给
CATCH 块中包含的另一个语句组。

示例:

BEGIN TRY

    SQL 语句组1

END TRY

BEGIN CATCH

    SQL 语句组2

END CATCH;

3.19.   TOP子句

在SQL Server
2005中加强了TOP的使用,尽量使用TOP(变量)来减少SQL拼串现象。

3.20.   TRANSACTION编写

只要在例程中使用多个数据库修改语句,包括在一个循环中多次执行一个语句,就应考虑声明显式事务。在SQL
SERVER 2005 中,增加了TRY块可进行很好的应用。

实例:

   
BEGIN TRY

        BEGIN TRANSACTION;

        UPDATE [HumanResources].[Employee]

        SET [Title] = @Title

            ,[HireDate] = @HireDate

            ,[CurrentFlag] = @CurrentFlag

        WHERE [EmployeeID] = @EmployeeID;

        INSERT INTO
[HumanResources].[EmployeePayHistory]

            ([EmployeeID]

            ,[RateChangeDate]

            ,[Rate]

            ,[PayFrequency])

        VALUES (@EmployeeID, @RateChangeDate, @Rate,
@PayFrequency);

        COMMIT TRANSACTION;

    END TRY

    BEGIN CATCH

        — Rollback any active or uncommittable
transactions before

        — inserting information in the
ErrorLog

        IF @@TRANCOUNT > 0

        BEGIN

            ROLLBACK TRANSACTION;

        END

        EXECUTE [dbo].[uspLogError];

   
END CATCH;

3.21.   存储过程

在编写存储过程时,使用PROCEDURE 代替 PROC 简写。

示例:CREATE PROCEDURE [dbo].[存储过程名字]

代码注释

4.1.代码头部注释

在SQL代码块(sql文件或存储过程)的头部进行注释,标注创建人(Author)、创始日期(Create date)、修改信息(Modify [n])。

格式:


Author:      <Author,,Name>

— Create
date: <Create Date,,>


Description: <Description,,>

— Modify
[n]:  < Modifier,Date, Description >

示例:


Author:      Zhanghaifeng

— Create
date: 2006-12-25


Description: H2000报关单回执处理

— Modify
[1]:  郑佐,
2006-12-31, 简化逻辑判断流程

— Modify
[2]:  郑佐,
2007-01-20, 更新条件判断

注:日期格式使用
yyyy-MM-dd。Modify [n] n代表修改序号,从1开始,每次修改加1。

4.2.TRANSACTION注释

建议在每个事务的开头进行注释,说明该事务的功能。

— <
Modifier,Date, Description >

BEGIN TRANSACTION;

附录A  命名规则

常见命名规则有四种样式:完全大写、完全小写、Pascal
大小写和 Camel 大小写。

5.1.Pascal 大小写

组成标识符的每个单词的首字母大写,其余字母小写的书写约定。对于缩写的双字母单词,要求全部大写。

例如:ApplicationException

      ID

5.2.Camel 大小写

标识符的首字母小写,每个后面连接的单词的首字母大写,其余字母小写的书写约定。对于缩写的双字母单词,要求它们出现在标识符首部时全部小写,否则全部大写。

例如:applicationException

      id

5.3.匈牙利命名法

匈牙利命名法由匈牙利程序员发明,他在微软工作了多年,此命名法就是通过微软的各种产品和文档传出来。多数有经验的程序员,不管他们用的是哪门语言,都或多或少在使用它。

基本原则:变量名 = 属性
+ 类型 + 对象描述

即一个变量名是由三部分信息组成,这样,程序员很容易理解变量的类型、用途,而且便于记忆。

附录B  参考资源

6.1.Microsoft SQL Server 2005 联机丛书

http://www.microsoft.com/downloads/details.aspx?displaylang=zh-cn&FamilyID=BE6A2C5D-00DF-4220-B133-29C1E0B6585F

6.2.SQL Server 2005示例数据库

AdventureWorks

AdventureWorksDW

6.3.编写可移植的 Transact-SQL 代码

http://www.microsoft.com/china/msdn/library/data/sqlserver/USsqldnsqldevdev\_06112004L.mspx

6.4.T-SQL 编码标准

http://www.microsoft.com/china/msdn/library/data/sqlserver/sp04l9.mspx