非规范化设计的主要优点是减少了查询操作所需的连接;减少了外部键和索引的数量;可以预先进行统计计算,提高了查询时的响应速度。非规范化存在的主要问题是增加了数据冗余;影响数据库的完整性;降低了数据更新的速度;增加了存储表所占用的物理空间。其中最重要的是数据库的完整性问题。这一问题一般可通过建立触发器、应用事务逻辑、在适当的时间间隔运行批命令或存储过程等方法得到解决。
5)物理设计阶段
数据库在物理设备上的存储结构与存取方法称为数据库的物理结构,它依赖于给定的计算机系统。为一个给定的逻辑数据模型选取一个最适合应用要求的物理结构的过程,就是数据库的物理设计。
(1)将逻辑数据模型转换成目标DBMS
在物理设计阶段,首先将逻辑设计阶段得到的模型转换为特定数据库管理系统的对象。
(2)SQL Server中对象的设计
建立数据表后,还要建立一系列数据库对象,来辅助数据库的各种操作。下面以SQL Server数据库为例,介绍数据库系统的一些对象的建立和应用。
①视图(View)。
视图是一个虚拟表,其内容由查询定义。同真实的表一样,视图包含一系列带有名称的列和行数据。但是,视图在数据库中不是以存储的数据集合形式存在。行和列数据来自由定义视图的查询所引用的表,并且在引用视图时动态生成。
对其中所引用的基础表来说,视图的作用类似于筛选。定义视图的筛选可以来自当前或其他数据库的一个或多个表,或者其他视图。分布式查询也可用于定义使用多个异类源数据的视图。如果有几台不同的服务器分别存储组织中不同地区的数据,而需要将这些服务器上相似结构的数据组合起来,这种方式就很有用。
视图的创建:
CREATE VIEW[.][.]view_name[(column,...n])]
[WITH[,...n]]
AS
select_statement
[WITH CHECK OPTION]
:={ENCRYPTION|SCHEMABINDING|VIEW_METADATA}
下例创建具有简单SELECT语句的视图。当需要频繁地查询列的某种组合时,简单视图非常有用。
USE pubs
IF EXISTS(SELECT TABLE_NAME FROM INFORMATION_SCHEMA.VIEWS
WHERE TABLE_NAME=’titles_view’)
DROP VIEW titles_view
GO
CREATE VIEW titles_view
AS
SELECT title,type,price,pubdate
FROM titles
GO
SQLSERVER中可以用drop和alter语句删除和修改视图。
②函数(function)。
函数是由一个或多个Transact—SQL语句组成的子程序,可用于封装代码以便重新使用。Microsoft SQL Server 2000并不将用户限制在定义为Transact—SQL语言一部分的内置函数上,而是允许用户创建自己的用户定义函数。可使用CREATE FUNCTION语句创建、使用ALTERFUNCTION语句修改及使用DROPFUNCTION语句除去用户定义函数。每个完全合法的用户定义函数名(database_name.owner_name.function_name)必须唯一。SQL Server2000支持3种用户定义函数:标量函数,内嵌表值函数和多语句表值函数。
这里主要介绍前两类。
标量函数:标量函数返回在RETURNS子句中定义的类型的单个数据值。下面是一个返回nvarchar类型的示例:
use northwind
create function fn_NewRegion(@myinput nvarchar(30))
returns nvarchar(30)
begin
if@myinput is null
set@myinput=’Not Applicable’
return@myinput
end
go
内嵌表值函数:表值函数返回table。下面例子返回内嵌表值函数。
USE pubs
GO
CREATE Function SalesByStore(@storeid varchar(30))
RETURNS TABLE
AS
RETURN(SELECT title,qty
FROM sales s,titles t
WHERE s.stor_id=@storeid and
t.title_id=s.title_id)
存储过程(storeprocedure)。存储过程是SQL语句和可选控制流语句的预编译集合,以一个名称存储,并作为一个单元处理。存储过程存储在数据库内,可由应用程序通过调用执行,而且允许用户声明变量、有条件执行及其他强大的编程功能。存储过程可包含程序流、逻辑及对数据库的查询。它们可以接受参数、输出参数、返回单个或多个结果集以及返回值。
下面的例子同时显示了3种不同的返回操作。
存储过程同时返回:使用“select”选出的数据集,输出形参,return输出。
create procedure dbo.materialbyout(@code int,@name varchar(30)output)
as
select*from r2_mdetail
select@name=mname from r2_mdetail where mcode=@code
return(select mpprice from r2_mdetail where mcode=@code)
go
以下是对于上面存储过程的调用,用户可以看到如何调用不同的返回值。
declare@a varchar(30)
declare@b int
exec@b=materialbyout 1,@name=@a output
select@a
select@b
③索引(index)。
可以利用索引快速访问数据库表中的特定信息。索引是对数据库表中一个或多个列[例如,employee表的姓氏(lname)列]的值进行排序的结构。如果想按特定职员的姓来查找他或她,则与在表中搜索所有的行相比,索引有助于更快地获取信息。
索引提供指针以指向存储在表中指定列的数据值,然后根据指定的次序排列这些指针。数据库使用索引的方式与使用书的目录很相似:通过搜索索引找到特定的值,然后跟随指针到达包含该值的行。
索引类型:根据数据库的功能,可在数据库设计器中创建3种类型的索引——唯一索引、主键索引和聚集索引。以下主要介绍前两种索引。
唯一索引:唯一索引不允许两行具有相同的索引值。
如果现有数据中存在重复的键值,则大多数数据库都不允许将新创建的唯一索引与表一起保存。当新数据将使表中的键值重复时,数据库也拒绝接受此数据。例如,如果在employee表中的职员姓氏(lname)列上创建了唯一索引,则所有职员不能同姓。
创建唯一索引操作步骤如下。
a.在数据库关系图中选择要创建索引的表,右击该表,然后从快捷菜单中选择【索引/键】命令。
b.或者,为要创建索引的表打开表设计器,在表设计器中右击,然后从快捷菜单中选择【索引/键】命令。
c.选择【新建】命令。【选定的索引】列表显示系统分配给新索引的名称。
d.在【列名】下选择要创建索引的列,可以选择多达16列。为获得最佳性能,只为每个索引选择一列或两列。对所选的每个索引,指出索引是按升序还是降序组织列值。
e.选择【创建UNIQUE】复选框。
f.选择【索引】选项。
g.如果要忽略将在索引中创建重复键的新数据或更新数据(使用INSERT或UPDATE语句),则选择【忽略重复键】选项。
当保存表或关系图时,索引即创建在数据库中。如果某列有多行包含NULL值,则不能在该列上创建唯一索引。同样,如果列的组合中有多行包含NULL值,则不能在多个列上创建唯一索引。在创建索引时,这些被视为重复的值。
主键索引:数据库表通常有一列或列组合,其值用来唯一标识表中的每一行,该列称为表的主键。
在数据库关系图中为表定义一个主键将自动创建主键索引,主键索引是唯一索引的特殊类型。主键索引要求主键中的每个值是唯一的。当在查询中使用主键索引时,它还允许快速访问数据。
④约束(check)。
约束定义关于列中允许值的规则,是强制完整性的标准机制。使用约束优先于使用触发器、规则和默认值。查询优化器也使用约束定义生成高性能的查询执行计划。
SQL Server2000支持五类约束。
NOTNULL指定不接受NULL值的列。
CHECK约束对可以放入列中的值进行限制,以强制执行域的完整性。
CHECK约束指定应用于列中输入的所有值的布尔(取值为TRUE或FALSE)搜索条件,拒绝所有不取值为TRUE的值。可以为每列指定多个CHECK约束。下例显示名为chk_id约束的创建,该约束确保只对此关键字输入指定范围内的数字,以进一步强制执行主键的阈。
CREATE TABLE cust_sample
(
cust_id int PRIMARY KEY,
cust_name char(50),
cust_address char(50),
cust_credit_limit money,
CONSTRAINT chk_id CHECK (cust_id BETWEEN 0 and 10000)
)
UNIQUE约束在列集内强制执行值的唯一性。
对于UNIQUE约束中的列,表中不允许有两行包含相同的非空值。主键也强制执行唯一性,但主键不允许空值。UNIQUE约束优先于唯一索引。PRIMARYKEY约束标识列或列集,这些列或列集的值唯一标识表中的行。在一个表中,不能有两行包含相同的主键值。不能在主键内的任何列中输入NULL值。在数据库中NULL是特殊值,代表不同于空白和0值的未知值。建议使用一个小的整数列作为主键。每个表都应有一个主键。一个表中可以有一个以上的列组合,这些组合能唯一标识表中的行,每个组合就是一个候选键。数据库管理员从候选键中选择一个作为主键。例如,在part_sample表中,part_nmbr和part_name都可以是候选键,但是只将part_nmbr选作主键。
CREATE TABLE part_sample
(part_nmbr int PRIMARY KEY,
part_name char(30),
part_weight decimal(6,2),
part_color char(15))
FOREIGNKEY约束标识表之间的关系。
一个表的外键指向另一个表的候选键。当外键值没有候选键时,外键可防止操作保留带外键值的行。在下例中,order_part表建立一个外键,引用前面定义的part_sample表。通常情况下,order_part在order表上也有一个外键,下面只不过是一个简单示例。
CREATE TABLE order_part
(order_nmbr int,
part_nmbr int
FOREIGN KEY REFERENCES part_sample(part_nmbr)
ON DELETE NO ACTION,
qty_ordered int)
GO
如果一个外键值没有候选键,则不能插入带该值(NULL除外)的行。如果尝试删除现有外键指向的行,ONDELETE子句将控制所采取的操作。ONDELETE子句有两个选项:
NOACTION指定删除由于错误而失败。
CASCADE指定还将删除包含指向已删除行的外键的所有行。
如果尝试更新现有外键指向的候选键值,ON UPDATE子句将定义所采取的操作。它也支持NOACTION和CASCADE选项。
⑤规则(rule)。
规则是一个向后兼容的功能,用于执行一些与CHECK约束相同的功能。CHECK约束是用来限制列值的首选标准方法。CHECK约束比规则更简明,一个列只能应用一个规则,但是却可以应用多个CHECK约束。CHECK约束作为CREATETABLE语句的一部分进行指定,而规则以单独的对象创建,然后绑定到列上。
下例创建一个规则,执行与前面主题中的CHECK约束示例相同的功能。Microsoft SQL ServerTM 2000首选的方法是CHECK约束。
CREATE RULE id_chk AS@id BETWEEN 0 and 10000
GO
CREATE TABLE cust_sample
(
cust_id int PRIMARY KEY,
cust_name char(50),