nt Not Null Default 0 Constraint ck_ArticleType Check(Type in (0,1,2)), -- 0,原创;1,编译;2,翻译
IsOnIndex Bit Not Null Default 1, -- 是否显示在首页
Content Text Not Null,
SourceCode Varchar(100) Null, -- 程序源码的下载路径
Source Varchar(50) Not Null Default 'TraceFact', -- 文章出处
SrcUrl Varchar(150) Null, -- 文章出处的URL
PostDate DateTime Not Null Default GetDate(),
ViewCount Int Not Null Default 0,
ClassId Int Not Null -- 外键包含的字段,文章类别
Constraint pk_Article Primary Key(Id) -- 建立主键
) 可以看到,在这里我使用了 Check 约束,以确保文章类型只能为 0,1,2。这里,我想说的是Check 约束的命名规则:尽管Check约束是针对字段的,但在同一数据库中,却不能有同名的Check约束。所以,建议使用 ck_ + 表名 + 字段名 来命名它,比如这个范例脚本中的 ck_ArticleType。
除此以外,我还使用了Unique约束,以确保文章标题的唯一性。由于这是我的博客文章表,不应该出现重复的题目,这样可以避免在使用 Insert 语句时插入重复值。类似于Check约束,这里的命名规则是:uq_ + 表名 + 字段名。
主键的命名
按照SQL Server 的默认规范(使用企业管理器创建主键时默认产生的主键名),主键的命名为 pk_TableName。主键是针对一个表的,而不是针对一个字段的,大家有时候在企业管理器中会见到一个表的两个字段前面都会有钥匙的图标(比如SQL Server 2000自带的NorthWind范例数据库的EmployeeTerritories表),就会误以为主键是针对字段的,即是说一个表上有两个主键,其实错了,只有一个主键,但包含了两个字段,这就是常说的复合主键。为了有个更生动的认识,看下建立复合主键的SQL语句,以上面说到的多对多连接表StudentCourse为例:
Alter Table StudentCourse
Add Constraint pk_StudentCourse Primary key(StudentId, CourseId)
可见,对于主键pk_StudentCourse,包含了两个字段StudentId 和 CourseId。
外键的命名
外键的命名为 fk_外键所在的表名_外键引用的表名。因为外键所在的表为从表,所以上式可以写为 fk_从表名_主表名。
外键包含的字段的命名,外键包含的字段和外键是完全不同的概念。外键包含字段的命名,建议为:外键所在的表名 + Id。
考虑这样一个关系,表Hotel,字段Id, Name, CityId。表City,字段Id,Name。因为一个城市可能有好多家酒店,所以是一个一对多的关系,City是主表(1方),Hotel是从表(多方)。在Hotel表中,CityId是做为外键使用。
在实现外键的时候我们可以这样写:
Alter Table HotelInfo
Add Constraint fk_HotelInfo_City Foreign Key (CityID) References City(ID)
On Delete No Action On update No Action
很明显,fk_HotelInfo_City是外键的名字,CityId是外键包含的字段的名字。
NOTE:在创建数据库表的时候,一般需要写成三个SQL脚本文件。第一个文件仅包含所有的创建表的SQL语句,即Create Table 语句。第二个文件包含删除关系和表的语句,其中,所有删除关系的语句,即Drop Constraint 语句集中在这个文件的上半部分,所有删除表的语句,Drop Table语句,集中在这个文件的下半部分。第三个文件包含建立表之间关系的语句。这种做法会在你移植数据库的时候产生较大的便利,原因我就不解释了,您一试便知。
而对于多对多关系中解析表的外键包含的字段,顺理往下推,我们可以这样写(再次回到学生选课的多对多例子中):
建立解析表StudentCourse与Student表的外键关系:
Alter Table StudentCourse
Add Constraint fk_StudentCourse_Student Foreign Key (StudentId) References Student (Id)
On Delete No Action On Update No Action
建立解析表StudentCourse与Course 表的外键关系:
Alter Table StudentCourse
Add Constraint fk_StudentCourse_Course Foreign Key (CourseId) References Course(Id)
On Delete No Action On Update No Action
触发器的命名
由三部分构成:
- 前缀(tr),描述了数据库对象的类型。
- 基本部分,描述触发器所加的表。
- 后缀(_I、_U、_D),显示了修改语句(Insert, Update及Delete)
存储过程的命名
大家知道,系统存储过程的前缀是 sp_,为了避免将用户存储过程与系统存储过程混淆,这里我推荐大家使用 pr 作为自己定义的存储过程的命名。
同时,命名的规则是:采用自解释型的命名,比如:prGetItemById。
这里,有个有意思的地方值得深思。我们按上面规则命名存储过程的时候,可以用两种方式:
- 动词放前面,名词放后面。
- 名词放前面,动词放后面。
我个人推荐使用方式2,现在说说原因:
以NorthWind 为例,假如对于 Employees 表你有4个存储过程,分别命名为:prEmployeeInsert、prEmployeeUpdate、prEmployeeDelById、prEmployeeGetById
同时对于 Products 表你有类似的4个存储过程,分别命名为:prProductInsert、prProductUpdate、prProductDelById、prProductGetById
这时,你用企业管理器查看时,会发现存储过程像下面这样整整齐齐的排列:
prEmployeeDelById
prEmployeeGetById
prEmployeeInsert
prEmployeeUpdate
prProductDelById
prProductGetById
prProductInsert
prProductUpdate
很容易就会发现,当你的存储过程越多时,这种命名方法的优势就越明显。
存储过程中参数的命名
存储过程中的入口参数,我建议与其对应的字段名相同,这里,假设要写一个更新Northwind数据库Employees表的存储过程(做了简化),可以这么写:
Create Procedure prEmployeeUpdateById
@EmployeeId Int,
@LastName NVarchar(20),
@FirstName NVarchar(10)
As
Update Employees Set
LastName = @LastName,
FirstN