约束

关系数据库存储分解为多个表的数据,每个表存储相应的数据
利用键来建立从一个表到另一表的引用(由此产生了术语引用完整性(referential integrity))

正确地进行关系数据库涉及,需要一种方法保证只在表中插入合法数据
例如,如果 Orders 表存储订单信息,OrderItems 表存储订单详细内容,应该保证 OrderItems 中引用的任何订单 ID 都存在于 Orders 中;类似地,在 Orders 表中引用的任意顾客必须存在于 Customers 表中

虽然可以在插入新行时进行检查(在另一个表上执行 SELECT ,以保证所有值合法并存在),但最好不要这样做,因为:
1、如果在客户端曾main上实施数据库完整性规则,则每个客户端都要被迫实施这些规则,一定会有一些客户端不实施这些规则
2、在执行 UPDATE 和 DELETE 操作时,也必须实施这些规则
3、执行客户端检查非常耗时,而 DBMS 执行这些检查会相对高效

约束(constraint):
管理如何插入或处理数据库数据的规则

DBMS 通过在数据库表上施加约束实施引用完整性
大多数约束是在表定义中定义的,用 CREATE TABLE 和 ALTER TABLE 语句

主键

主键是一种特殊的约束,用来保证一列(或一组列)中的值是唯一的,而且永不改动;即,表中的一列(或多个列)的值唯一标识表中的每一行

定义主键:

CREATE TABLE Vendors
(
vend_id CHAR(10) NOT NULL PRIMARY KEY,
vend_name CHAR(50) NOT NULL,
vend_address CHAR(50) NULL,
vend_city CHAR(50) NULL,
vend_state CHAR(5) NULL,
vend_zip CHAR(10) NULL,
vend_country CHAR(50) NULL
);
ALTER TABLE Vendors
ADD CONSTRAINT PRIMARY KEY (vend_id);
外键

外键是表中的一列,其值必须列在另一表的主键中
外键是保证引用完整性的极其重要的部分

举例说明,Orders 表将录入到系统的每个订单作为一行包含其中;
顾客信息存储在 Customers 表中;
Orders 表中的订单通过顾客 ID 于 Customers 表中的特定行相关联;
顾客 ID 为 Customers 表的主键,每个顾客都有唯一的 ID;
订单号为 Orders 表中的主键,每个订单都有唯一的订单号

Orders 表中顾客 ID 列的值不一定是唯一的;如果某个顾客有多个订单,则多行具有相同的顾客 ID(虽然订单号不同)
同时,Orders 表中顾客 ID 列的合法值为 Customers 表中顾客的 ID

在 Orders 的顾客 ID 列上定义了一个外键,因此该列只能接受 Customers 表的主键值
定义外键的方法:

CREATE TABLE Orders
(
order_num INTEGER NOT NULL PRIMARY KEY,
order_date DATETIME NOT NULL,
cust_id CHAR(10) NOT NULL REFERENCES
➥ Customers(cust_id)
);

表定义使用了 REFERENCES 关键字,它表示 cust_id 中的任何值都必须是 Customers 表的 cust_id 中的值

相同的工作,也可以在 ALTER TABLE 语句中使用 CONSTRAINT 完成

ALTER TABLE Orders
ADD CONSTRAINT
FOREIGN KEY (cust_id) REFERENCES Customers (cust_id)

外键有助于防止意外删除:在定义了外键后,DBMS 不允许删除在另一个表中具有关联行的行

唯一约束

唯一约束用来保证一列(或一组列)中的数据是唯一的,它们类似于主键,但是存在以下重要区别:

  1. 表可以包含多个唯一约束,但是每个表只允许一个主键
  2. 唯一约束列可以包含 NULL 值
  3. 唯一约束列可以修改或者更新
  4. 唯一约束列的值可以重复使用
  5. 与主键不同,唯一约束不能用来定义外键
检查约束

检查约束用来保证一列(或者一组列)中的数据满足一组指定的条件
检查约束的常见用途有:

  1. 检查最大或者最小值
  2. 指定范围
  3. 只允许特定的值
CREATE TABLE OrderItems
(
order_num INTEGER NOT NULL,
order_item INTEGER NOT NULL,
prod_id CHAR(10) NOT NULL,
quantity INTEGER NOT NULL CHECK (quantity > 0),
item_price MONEY NOT NULL
);

利用这个约束,任何插入或者更新的行都会被检查,保证 quantity 的值大于 0

用户定义数据类型:
有的 DBMS 允许用户定义自己的数据类型,它们是定义检查约束(或者其他约束)的基本简单数据类型

索引

索引用来排序数据以加快搜索和排序操作的速度

主键数据总是排序的,这是 DBMS 的工作,因此,按主键检索特定行总是一种快速有效的操作
但是,搜索其他列中的值通常效率不高,解决办法就是使用索引

可以在一个或多个列上定义索引,使 DBMS 保存其内容的一个排过序的列表
定义了索引后,DBMS 以使用书中的索引类似的方式使用它,搜索排过序的索引,找出匹配的位置,然后检索

在开始创建索引前,应该了解:

  1. 索引改善检索操作的性能,但是降低了数据插入、修改和删除的性能,在执行这些操作时,DBMS 必须动态地更新索引
  2. 索引数据可能要占用大量的存储空间
  3. 并非所有的数据都适合做索引,取值不多的数据不如具有更多可能值的数据,能通过索引得到那么多的好处
  4. 索引用于数据过滤和数据排序,如果经常以某种特定的顺序排序数据,则该数据可能适合做索引
  5. 可在索引中定义多个列,则可以实现只在特定情况下进行排序,在其他单个列或非全部索引列使用时,不使用索引

不同的 DBMS 中创建索引的方式不同

CREATE INDEX prod_name_ind
ON Products (prod_name);

索引必须唯一命名

检查索引:
索引的效率随表数据的增加或改变而变化;最好定期检查索引,并根据需要进行调整

触发器

触发器时特殊的存储过程,它在特定的数据库活动发生时自动执行
触发器可以与特定表上的 INSERT、UPDATE 和 DELETE 操作(组合)相关联

与存储过程不一样(存储过程只是简单的存储 SQL 语句),触发器与单个的表相关联
与 Orders 表上的 INSERT 操作相关联的触发器只在 Orders 表中插入行时执行

触发器内的代码具有以下数据的访问权:

  1. INSERT 操作中的所有新数据
  2. UPDATE 操作中的所有新数据
  3. DELETE 操作中删除的数据

根据所使用的 DBMS 的不同,触发器可在特定操作执行之前或者之后执行

触发器的常见用途:

  1. 保证数据一致,例如,在 INSERT 和 UPDATE 操作中将所有州名转换为大写
  2. 基于某个表的变动在其他表上执行活动,例如,每当更新或删除一行时,将审计跟踪记录写入某个日志表
  3. 进行额外的验证并根据需要回退数据,例如,保证某个顾客的可用资金不超限定,如果已经超了,则阻塞插入
  4. 计算计算列的值或更新时间戳

一般来说,约束的处理比触发器块,在可能的时候,尽量使用约束

数据库安全

任何安全系统的基础都是用户授权和身份确认
这是一种处理,通过这种处理对用户进行确认,保证他是有权用户,允许执行他要执行的操作

一般来说,需要保护的操作有:

  1. 对数据库管理功能(创建表、更改或者删除已存在的表等)的访问
  2. 对特顶数据库或者表的访问
  3. 访问的类型(只读、对特定列的访问等)
  4. 仅通过视图或存储过程对表进行访问
  5. 创建多层次的安全措施,从而允许多种基于登录的访问和控制
  6. 限制管理用户账号的能力