完整性约束:
- 域约束适用于数据类型
- 属性约束适用于列
- 关系约束适用于单个表中的行
- 数据库约束适用于表与表之间
域约束
域约束(Domain Constraint)通常是指对数据类型有效值范围的限制。在数据库系统中,你可以为某个特定的数据类型定义一个域,并且规定在这个域中数据可以取的值。这就像是为数据类型设定了一个子集,只有这个子集中的值才是合法的。
例如,在SQL中,你可以创建一个颜色的域,只允许某些预定义的颜色作为有效值:
CREATE DOMAIN Colour AS VARCHAR(15)
CHECK (VALUE IN ('red', 'blue', 'green', 'yellow'));
在这个例子中,Colour
域被定义为一个字符串类型(VARCHAR(15)
),并且只接受 'red', 'blue', 'green', 'yellow' 这几个值。如果试图插入或更新非这些指定值的颜色,数据库将会拒绝该操作。
将域约束应用于数据库中的列时,该列只能接受域中定义的有效值。域约束可以帮助保证数据的准确性和一致性,因为它限制了可以输入到数据库列中的值。
需要注意的是,并非所有数据库系统都支持CREATE DOMAIN
语句。在不支持的系统中,可以使用CHECK
约束来模拟域约束的行为。例如,在创建表时,可以对列指定CHECK
约束:
CREATE TABLE Dress
(
Colour VARCHAR(15) CHECK (Colour IN ('red', 'blue', 'green', 'yellow'))
);
这个CHECK
约束会确保Colour
列只能包含 'red', 'blue', 'green', 'yellow' 这几个预定义的颜色值。
示例
在支持CREATE DOMAIN
命令的数据库系统中,如PostgreSQL,你可以先定义一个域,然后在创建表时使用这个域作为列的数据类型。下面是如何在支持CREATE DOMAIN
的数据库系统中创建域约束和表的步骤:
步骤 1: 创建域
首先,创建一个域约束,指定允许的数据类型和有效值范围。
CREATE DOMAIN color_domain AS VARCHAR(15)
CHECK (VALUE IN ('red', 'blue', 'green', 'yellow'));
这里,color_domain
是一个自定义的域,它被限制为只能包含指定的几个字符串值。
步骤 2: 使用域创建表
然后,你可以在创建新表时使用这个域作为列的数据类型。
CREATE TABLE Dress
(
size INT,
color color_domain
);
在这个Dress
表的定义中,color
列使用了之前定义的color_domain
域作为其数据类型。任何尝试插入或更新不在域约束内的color
列的操作都会被数据库拒绝。
请注意,这些命令适用于支持CREATE DOMAIN
的数据库系统,如PostgreSQL。如果你在MySQL等不支持CREATE DOMAIN
命令的数据库系统中工作,你需要使用不同的方法(通常是CHECK
约束)来实现相同的功能。
断言 Assertions
- 断言提供了一种指定关系和数据库约束的方法
CREATE ASSERTION <name> CHECK (<condition>);
- 断言陈述了一个必须始终为真的布尔条件
- 任何会使条件变为假的操作都是不允许的
<condition>
可以指代一个或多个表- 经常使用 EXISTS 或 NOT EXISTS
- 注意:Oracle不支持!
断言是数据库约束的一种形式,用来保证一定的业务规则在数据库中始终为真。例如,一个断言可以用来确保一个条件(如某个表中的某个值)始终满足。如果某个数据库操作会导致这个条件不满足,那么这个操作会被拒绝。
断言可以覆盖一个或多个表,并且可以使用EXISTS
或NOT EXISTS
这样的逻辑操作来定义复杂的条件。然而,值得注意的是,虽然断言是SQL标准的一部分,但并非所有的数据库系统都支持断言,比如Oracle就不支持。
关系约束
- 要创建关系约束,我们只需创建一个断言,该断言在单个表上检查给定的约束
- 例如,在Employee表中,任何Bonus都不应该超过员工Salary的15%
关系约束通常是指单个表内的约束,用于确保表内数据的一致性。例如,你可以设置一个关系约束来保证员工的奖金不超过其薪水的15%。这是通过在数据库中创建一个断言来实现的。这个断言使用一个NOT EXISTS
子查询来检查是否有任何员工的奖金超过了其薪水的15%。如果存在这样的员工,断言会失败,任何试图违反这一规则的操作都会被阻止。
CREATE ASSERTION checkSalaryBonus CHECK
(
NOT EXISTS
(
SELECT * FROM Employee WHERE Bonus > 0.15*Salary
)
);
数据库约束
- 数据库约束类似于关系约束,但它们引用多个表
Example:
Given tables Student(ID, Name, Department)
and Enrolment(ID, Module)
, make sure no computer science student takes more than 12 modules
CREATE ASSERTION CSenrolment CHECK
(
NOT EXISTS
(
SELECT *
FROM Student AS S
WHERE S.Department = 'computer science'
AND (SELECT COUNT(*) FROM Enrolment AS E WHERE S.ID = E.ID) > 12
)
);
在Oracle数据库中,虽然不支持域(Domains)或断言(Assertions),但是它支持使用CHECK
约束来实现行级别的约束。
行级约束用来限制表中单个行上的数据。它可以确保插入或更新的数据符合特定的条件。如果这些条件不被满足,数据库将拒绝这个操作。
行级约束和其他类型的约束一样被声明。这里是一个声明行级约束的例子:
CONSTRAINT <name> CHECK (<condition>);
在这个语句中,<name>
是你给约束起的名字,而<condition>
是必须满足的条件。例如,你可以创建一个约束,确保员工的奖金不超过他们薪水的一定比例。
- add a check on the Employee table to make sure no employee’s Bonus is more than 15% of their Salary
ALTER TABLE Employee
ADD CONSTRAINT checkSalaryBonus
CHECK (Bonus < 0.15*Salary);
相较于断言,行级约束的作用范围更小,因为它们只针对单个表中的单行数据,而不是像断言那样可以跨越多个表。这意味着每当表中的一行数据被插入或更新时,CHECK
约束都会检查该行数据是否符合条件。如果不符合,操作将会被拒绝。这种方式可以有效地在数据库中强制执行数据验证规则,保持数据的完整性和准确性。