SQLServer开发通用规范.docx

上传人:b****7 文档编号:25585903 上传时间:2023-06-10 格式:DOCX 页数:24 大小:29.69KB
下载 相关 举报
SQLServer开发通用规范.docx_第1页
第1页 / 共24页
SQLServer开发通用规范.docx_第2页
第2页 / 共24页
SQLServer开发通用规范.docx_第3页
第3页 / 共24页
SQLServer开发通用规范.docx_第4页
第4页 / 共24页
SQLServer开发通用规范.docx_第5页
第5页 / 共24页
点击查看更多>>
下载资源
资源描述

SQLServer开发通用规范.docx

《SQLServer开发通用规范.docx》由会员分享,可在线阅读,更多相关《SQLServer开发通用规范.docx(24页珍藏版)》请在冰豆网上搜索。

SQLServer开发通用规范.docx

SQLServer开发通用规范

SQL开发规范

文件编号:

文件版次:

文档编号

版本号

分册名称

sqlServer开发规范

第1册/共1册

总页数

正文

附录

编制

孙启琳

审批

生效日期

东软集团股份有限公司

 

修改记录

版本号

变更控制报告编号

更改条款及内容

更改人

审批人

更改日期

2010001

文档创建

孙启琳

2010-2-2

 

 

 

 

 

 

 

 

 

 

 

 

1.1目的

规范sql的编写格式,提高SQL语句的可读性,共享性和执行效率。

1.2使用范围

所有需要与数据库交互的应用系统。

1.3概述

大部分业务系统需要与数据库进行交互,与数据库交互的主要方式就是SQL语句,编写规范的SQL语句不但利于阅读,而且被数据库重复使用的几率也较大,执行效率相对较高,编写的好的SQL与编写的差的SQL在执行性能上可能会差几倍甚至几千几万倍,因此养成好的SQL编写规范对于提高项目质量及提高开发人员自身素质有着潜在的极大的影响。

1.4书写

SQL书写遵守如下规范:

在同一个项目中,为了最大限度实现SQL的共享,要求书写sql语句时大小写要一致,为了阅读方便和统一起见,所有SQL语句全部小写(如SQL谓词,字段名,表名等),常量除外,常量可以按需要书写。

举例:

下面两个相同的语句除常量外都要统一起来。

1)selectnamefromemp;

2)select‘NAME’fromempwhereemp_no=’QD001’

SQL语句尽可能放在一行,若SQL太长放在一行中影响阅读时可分多行,但要保持缩进一致,缩进可用TAB或者空格,但TAB数和空格数最好一致。

SQL语句中,各谓词之间以空格分割的,尽量保持空格数量一致,即若用一个空格分割,则全部都用一个空格分割,便于数据库能够共享。

能使用绑定变量的,尽量使用绑定变量,尤其是在前台程序中.

对下面列出的情况,慎重使用绑定变量:

1)列值倾斜严重,如:

某一状态列大部分值是‘1’,只有极少数值为’2’,这种情况不宜用绑定变量,而应该用常量,便于数据库使用柱状图统计信息。

2)日期时间列。

总之:

书写SQL的目标是若sql的用途是一样的,则sql应该完全一致,包括空格,大小写。

下面的语句由于写法不完全相同,数据库会理解为4条不同的语句从而导致重复编译,降低了性能。

1)selectnamefromempwhereemp_no=’111’

2)SelectnameFromempWhereemp_no=’111’

3)selectNamefromEMPwhereemp_no=’111’

4)selectnamefromempwhereEMP_NO=’111’

下面的语句,由于语句规范,可以只编译一次。

1)selectnamefromempwhereemp_no=’111’

2)selectnamefromempwhereemp_no=’222’

3)selectnamefromempwhereemp_no=’333’

4)selectnamefromempwhereemp_no=:

b1

1.5注释

1.5.1开头注释

所有的过程、函数、触发器、包都应该在开头有注释,

注释中要列出对象名称;完成功能简述;调用模块,调用时机;

创建日期;作者信息;历次修改日期;历次修改人;历次修改原因和其它作者认为重要的内容,在每次修改的注释之间建一空行。

举例如下:

/*************************************************************

名称:

PRO_WO_MULTI_REPAIR_JOB

功能:

多次维修判定程序

调用:

自动统计月结前,后台调用

作者:

xxx

时间:

2009-02-20

修改人:

xxx

修改时间:

2009-03-08

修改内容:

重写部分SQL优化性能

修改人:

xxx

修改日期:

2008-03-23

修改内容:

增加判断条件

*************************************************************/

1.5.2块注释

对于复杂的语句块,必须提供块注释,清晰描述该语句块的功能逻辑、数据结构以及算法;块注释应该和它们所描述的代码具有一样的缩进格式;块注释之首应该有一个空行,用于把块注释和代码分割开来;块注释结构如下所示:

/*

计算配送能力系数:

派工系数=a*b+c*d+e*f

a:

考评成绩,取xx的考评成绩

c:

承担度度,根据当前遗留量和总服务能力计算所得,

c=当前遗留配送量/总配送能力

...

*/

1.5.3行注释

对于复杂的SQL语句,必须提供行注释,清晰描述该SQL语句功能以及目的;行注释结构如下所示:

--计算动态能力得分,当负荷率超高时,可能出现负值,注意处理。

添加注释时要注意:

注释中包含GO命令时会生成一个错误消息。

1.5.4过程和函数

1.5.5命名规范

存储过程/函数的命名(代码)使用以下方式:

存储过程名=SP_+模块代码+存储过程代码

函数名=F_+模块代码+函数代码

存储过程以表现其功能的简洁语言进行命名,定义好后,放置于每一个Diagram的特定区域(一般置于右边部分的上边)。

1.5.6过程/函数头定义规范

包括过程/函数名称定义、参数定义、注释说明、变量定义四部分。

参数定义

所有的参数必须显示指出变量类型,对于返回参数,必须指出其方向;

参数变量定义格式为:

“a“+参数类型简写+“_”+参数名称,其中a是单词argument(参数)的第一个字母,参数类型如下:

文本型:

s

日期时间型:

d

数字型:

n

整形:

i

布尔型:

b

举例:

as_name标识文本型

ad_birthdate表示日期时间型

an_age表示数字型

注释说明

见前面描述。

1.5.7变量定义规范

(1).变量的命名

除游标变量以外,所有的变量命名采用此方式:

变量名=“v_”+变量名称

游标变量采用:

变量名=“cur”+变量名(第一个字母大写)。

其中变量名称由代表变量确切含意的单词代码组合而成,每一个单词的首字母根据阅读的方便性决定是否需要大写。

举例:

变量名:

v_EmpName

游标名:

curNetlist

(2).变量类型

定义变量的类型时,尽量采用显示定义的方式。

对于仅用于Oracle系列的数据库应用,也可以引用表、游标的引用定义方式。

尽量将变量的定义分开来,并进行格式化,以便程序代码的阅读。

例如:

v_UserNameCHAR(10)

v_SEXCHAR

(1)

1.5.8变量注释

原则上要求对于一般变量定义时必须加上注释,如变量有特定的值范围,则必须显示描述各确切值及其含意说明;

1.5.9过程/函数体定义规范

在过程/函数的定义中,最重要的是过程代码的严谨性和可读性,主要包括以下的注意事项:

(1).如无特殊需要,SQL中涉及的所有内容都要小写。

(2).原则上要求所有的SQL语句必须在其前面加上注释,对于IF/CASE等流程控制语句,必须在语句前/后说明控制处理和可能的流程方向;

(3).所有的赋值语句要求变量与运算符之间要有空格。

如:

v_Count:

=v_Count+1,并保持适当的对齐;

(4).尽量避免复杂SQL,尤其是关联多个大表的SQL,对于需要关联多个大表的SQL最好分解成小的SQL分步处理,避免出现性能问题,对于复杂的语句块之间,要求中间加入空行;

(5).所有可能的返回结果,必须在过程体中显示定义和说明,并在注释中说明。

在其它的过程、代码中调用本过程/函数时,必须在其代码中处理所有的各种可能的返回结果;

(6).锁定数据时,尽可能只锁定要操作的数据行,避免锁定整个表,限制使用localtable等DDL语句,若要对数据表、数据行加锁时,需要考虑由此导致的并发操作失败的处理;

(7).所有的过程/函数代码在编写之前,必须要有设计原型及其说明;

存储过程/函数错误定义

(1).所有的DML语句必须考虑死锁、并发、主关键字不唯一等的出错异常处理,应该对所有可能出现的异常进行捕获、编码处理,并注明异常的内容(注:

异常捕获及处理请参见);

(2).异常处理有两种需要考虑的问题,一是事务的完整性;二是错误的出错日志及返回处理。

所有异常的根据其类型和等级进行以下的处理:

类型

内容

处理

系统级

数据库级发出的底层的异常,如主关键字不唯一冲突等;

返回定义错误代码为其它错误,完全回退事务,登录异常日志;

应用级

应用系统定义并发出的异常,如指定记录不存在;

定义应用级错误代码,根据实际情况处理事务;

使用原则

(1).存储过程功能尽量保持独立、复用,但尽量避免嵌套调用,充分考虑其性能体现;

(2).使用前台代码调用存储过程时,必须考虑返回传入参数的有效性、代码的处理及展示、事务完整性处理;

(3).直接使用参数作为变量处理,不要在存储过程中定义参数同样含义的变量使用,避免由于值的不同导致性能问题。

1.6触发器

1.6.1命名规范:

触发器不同类型的命名结构如下

操作

时机

命名结构

Insert

After

ai_表名

Update

After

au_表名

Delete

After

ad_表名

1.6.2触发器编写规范

请参见存储过程/函数编写规范。

1.7异常

所有过程和函数处理必须考虑可能出现的错误,一是数据库或操作系统底层错误;二是由于业务逻辑造成的错误;三是无反应或超时;四是输入参数不在指定范围内。

设计所有的过程时,必须考虑出错后的恢复。

1.8优化

1.8.1SQL语句原则

Where子句尽量避免使用函数;

避免在ORDERBY子句中使用表达式;

限制在GROUPBY子句中使用表达式;

慎用游标;

大小写规范统一,变量绑定统一,避免重复编译;

尽可能少的返回结果集行的数量

避免使用select*语句;

减少结果集中的列的数量;

视图嵌套使用不能超过3层;

不要使用没有意义的列作为聚集索引列,例如,加1自增列;

避免隐式类型转换,例如字符型一定要用’’,数字型一定不要使用’’;

查询语句一定要有范围的限定,避免全表扫描操作;

合理对大表进行分区;

慎用DISTINCT关键字;

慎用UNION关键字,可以用OR替代;

使用top1替count(*)来判断是否存在记录;

1.8.2索引创建原则

同一索引中的组成列最好不要超过3列。

把经常一起出现的字段组合在一起,组成组合索引,组合索引的字段顺序与主键一样,也需要把最常用的字段放在前面,把重复率低的字段放在前面。

根据使用频率决定哪些字段需要建立索引,选择经常作为连接条件、筛选条件、聚合查询、排序的字段作为索引的候选字段。

根据数据量决定哪些表需要增加索引,数据量小的可以只有主键。

若某列中有大量的值是空值,可以建立索引。

要对值分布较宽的列建立索引。

若表主要用来查询,则可按需要建立索引,若对表操作主要是UPDATE,则尽可能少建索引。

不要对值较窄的列建立索引,如性别

不要索引较小的表(如表不足1000行)

若某列的值大部分是a,少数是别的值(如b,c,d…),且经常以该列的其它值(如b,c,d…)为查询条件,则可以将值a设为空值,并在此列上创建索引。

1.8.3充分利用索引

1.8.3.1函数、表达式使用

在where语句中,尽量避免在运算符左边对列进行函数或者表达式操作,容易引起全表扫描,要尽可能将操作移至运算符右边。

1.8.3.2IN/OR子句使用

IN、OR、NOTINSqlServer2005数据库可以分析出应该根据索引查找。

属于2005版本的新特性。

1.8.3.3!

=或<>操作符子句使用

!

=或<>操作符可以用INDEXSEEK查找的,可以正常使用。

1.8.3.4不要对索引字段进行运算

例如:

SELECTIDFROMTWHERENUM/2=100

应改为:

SELECTIDFROMTWHERENUM=100*2

SELECTIDFROMTWHERENUM/2=NUM1

如果NUM有索引应改为:

SELECTIDFROMTWHERENUM=NUM1*2

如果NUM1有索引则不应该改。

1.8.3.5不要对索引字段进行格式转换

日期字段的例子:

WHERECONVERT(VARCHAR(10),日期字段,120)=‘2008-08-15’

应该改为

WHERE日期字段〉=‘2008-08-15’AND日期字段<‘2008-08-16’

ISNULL转换的例子:

WHEREISNULL(字段,’’)<>’’应改为:

WHERE字段<>’’

WHEREISNULL(字段,’’)=’’不应修改

WHEREISNULL(字段,’F’)=’T’应改为:

WHERE字段=’T’

WHEREISNULL(字段,’F’)<>’T’不应修改

1.8.3.6不要对索引字段使用函数

WHERELEFT(NAME,3)='ABC'或者WHERESUBSTRING(NAME,1,3)='ABC'

应改为:

WHERENAMELIKE'ABC%'

日期查询的例子:

WHEREDATEDIFF(DAY,日期,'2005-11-30')=0应改为:

WHERE日期>='2005-11-30'AND日期<'2005-12-1‘

WHEREDATEDIFF(DAY,日期,'2005-11-30')>0应改为:

WHERE日期<'2005-11-30‘

WHEREDATEDIFF(DAY,日期,'2005-11-30')>=0应改为:

WHERE日期<'2005-12-01‘

WHEREDATEDIFF(DAY,日期,'2005-11-30')<0应改为:

WHERE日期>='2005-12-01‘

WHEREDATEDIFF(DAY,日期,'2005-11-30')<=0应改为:

WHERE日期>='2005-11-30‘

1.8.3.7不要对索引字段进行多字段连接

例如:

WHEREFAME+’.’+LNAME=‘’

应改为:

WHEREFNAME=‘H’ANDLNAME=‘Y’

1.8.3.8Like的使用

对索引列避免使用like‘%xx’,应该使用like‘xx%’。

设计数据结构时就应该考虑这个问题,不要出现必须要采用like‘%xx’才能满足业务需要的情形。

1.9设计

1.9.1数据库逻辑设计的规范化

第1规范:

没有重复的组或多值的列,这是数据库设计的最低要求。

第2规范:

每个非关键字段必须依赖于主关键字,不能依赖于一个组合式主关键字的某些组成部分。

消除部分依赖,大部分情况下,数据库设计都应该达到第二范式。

第3规范:

一个非关键字段不能依赖于另一个非关键字段。

消除传递依赖,达到第三范式应该是系统中大部分表的要求,除非一些特殊作用的表。

1.9.2合理的冗余

完全按照规范化设计的系统几乎是不可能的,除非系统特别的小,在规范化设计后,有计划地加入冗余是必要的。

冗余可以是冗余数据库、冗余表或者冗余字段,不同粒度的冗余可以起到不同的作用。

冗余可以是为了编程方便而增加,也可以是为了性能的提高而增加。

从性能角度来说,冗余数据库可以分散数据库压力,冗余表可以分散数据量大的表的并发压力,也可以加快特殊查询的速度,冗余字段可以有效减少数据库表的连接,提高效率。

1.9.3主键的设计

主键是必要的,SQLSERVER的主键同时是一个唯一索引,而且在实际应用中,我们往往选择最小的键组合作为主键,所以主键往往适合作为表的聚集索引。

聚集索引对查询的影响是比较大的,这个在下面索引的叙述。

在有多个键的表,主键的选择也比较重要,一般选择总的长度小的键,小的键的比较速度快,同时小的键可以使主键的B树结构的层次更少。

主键的选择还要注意组合主键的字段次序,对于组合主键来说,不同的字段次序的主键的性能差别可能会很大,一般应该选择重复率低、单独或者组合查询可能性大的字段放在前面。

1.9.4外键的设计

外键是最高效的一致性维护方法,数据库的一致性要求,依次可以用外键、CHECK约束、规则约束、触发器、客户端程序,一般认为,离数据越近的方法效率越高。

谨慎使用级联删除和级联更新,级联删除和级联更新作为SQLSERVER2000当年的新功能,在2005作了保留,应该有其可用之处。

因为级联删除和级联更新有些突破了传统的关于外键的定义,功能有点太过强大,使用前必须确定自己已经把握好其功能范围,否则,级联删除和级联更新可能让你的数据莫名其妙的被修改或者丢失。

从性能看级联删除和级联更新是比其他方法更高效的方法。

1.9.5字段的设计

字段是数据库最基本的单位,其设计对性能的影响是很大的。

需要注意如下:

A、数据类型尽量用数字型,数字型的比较比字符型的快很多。

B、数据类型尽量小,这里的尽量小是指在满足可以预见的未来需求的前提下的。

C、尽量不要允许NULL,除非必要,可以用NOTNULL+DEFAULT代替。

D、少用TEXT和IMAGE,二进制字段的读写是比较慢的,而且,读取的方法也不多,大部分情况下最好不用。

E、自增字段要慎用,不利于数据迁移。

1.9.6索引的设计

A、根据数据量决定哪些表需要增加索引,数据量小的可以只有主键。

B、根据使用频率决定哪些字段需要建立索引,选择经常作为连接条件、筛选条件、聚合查询、排序的字段作为索引的候选字段。

C、把经常一起出现的字段组合在一起,组成组合索引,组合索引的字段顺序与主键一样,也需要把最常用的字段放在前面,把重复率低的字段放在前面。

D、一个经常插入更新的表不要加太多索引,因为索引影响插入和更新的速度。

E、一个多用于查询的表可以适量增加索引,保证查询效率,例如报表系统。

1.10编码阶段

1.10.1尽可能少的范围数据

A、横向来看,不要写SELECT*的语句,而是选择你需要的字段。

B、纵向来看,合理写WHERE子句,不要写没有WHERE的SQL语句。

C、注意SELECTINTO后的WHERE子句,因为SELECTINTO把数据插入到临时表,这个过程会锁定一些系统表,如果这个WHERE子句返回的数据过多或者速度太慢,会造成系统表长期锁定,诸塞其他进程。

D、对于聚合查询,可以用HAVING子句进一步限定返回的行。

1.10.2尽可能少的重复操作

A、控制同一语句的多次执行,特别是一些基础数据的多次执行是很多程序员很少注意的。

B、减少多次的数据转换,也许需要数据转换是设计的问题,但是减少次数是程序员可以做到的。

C、杜绝不必要的子查询和连接表,子查询在执行计划一般解释成外连接,多余的连接表带来额外的开销。

D、合并对同一表同一条件的多次UPDATE,比如

UPDATEEMPLOYEESETFNAME=’H’WHEREEMP_ID=’F’

UPDATEEMPLOYEESETLNAME=’Y’WHEREEMP_ID=’F’

这两个语句应该合并成以下一个语句

UPDATEEMPLOYEESETFNAME=’H’,LNAME=’Y’WHEREEMP_ID=’F’

E、UPDATE操作不要拆成DELETE操作+INSERT操作的形式,虽然功能相同,但是性能差别是很大的。

F、不要写一些没有意义的查询,比如

SELECT*FROMEMPLOYEEWHERE1=2

1.10.3注意事务和锁

事务是数据库应用中和重要的工具,它有原子性、一致性、隔离性、持久性这四个属性,很多操作我们都需要利用事务来保证数据的正确性。

在使用事务中我们需要做到尽量避免死锁、尽量减少阻塞。

具体以下方面需要特别注意:

A、事务操作过程要尽量小,能拆分的事务要拆分开来。

B、事务操作过程不应该有交互,因为交互等待的时候,事务并未结束,可能锁定了很多资源。

C、事务操作过程要按同一顺序访问对象。

D、提高事务中每个语句的效率,利用索引和其他方法提高每个语句的效率可以有效地减少整个事务的执行时间。

E、尽量不要指定锁类型和索引,SQLSERVER允许我们自己指定语句使用的锁类型和索引,但是一般情况下,SQLSERVER优化器选择的锁类型和索引是在当前数据量和查询条件下是最优的,我们指定的可能只是在目前情况下更有,但是数据量和数据分布在将来是会变化的。

F、查询时可以用较低的隔离级别,特别是报表查询的时候,可以选择最低的隔离级别(未提交读)。

1.10.4注意临时表和表变量的用法

在复杂系统中,临时表和表变量很难避免,关于临时表和表变量的用法,需要注意:

A、如果语句很复杂,连接太多,可以考虑用临时表和表变量分步完成。

B、如果需要多次用到一个大表的同一部分数据,考虑用临时表和表变量暂存这部分数据。

C、如果需要综合多个表的数据,形成一个结果,可以考虑用临时表和表变量分步汇总这多个表的数据。

D、其他情况下,应该控制临时表和表变量的使用。

E、关于临时表和表变量的选择,很多说法是表变量在内存,速度快,应该首选表变量,但是在实际使用中发现,这个选择主要考虑需要放在临时表的数据量,在数据量较多的情况下,临时表的速度反而更快。

F、关于临时表产生使用SELECTINTO和CREATETABLE+INSERTINTO的选择,我们做过测试,一般情况下,SELECTINTO会比CREATETABLE+INSERTINTO的方法快很多,但是SELECTINTO会锁定TEMPDB的系统表SYSOBJECTS、SYSINDEXES、SYSCOLUMNS,在多用户并发环境下,容易阻塞其他进程,所以我的建议是,在并发系统中,尽量使用CREATETABLE+INSERTINTO,而大数据量的单个语句使用中,使用SELECTINTO。

G、注意排序规则,用CREATETABLE建立的临时表,如果不指定字段的排序规则,会选择TEMPDB的默认排序规

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 经管营销 > 销售营销

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1