数据库完整性

winterSky 2024-03-19 AM 289℃ 0条

2024-03-18T20:43:35.png

完整性约束:

  1. 域约束适用于数据类型
  2. 属性约束适用于列
  3. 关系约束适用于单个表中的行
  4. 数据库约束适用于表与表之间

域约束

域约束(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不支持!

断言是数据库约束的一种形式,用来保证一定的业务规则在数据库中始终为真。例如,一个断言可以用来确保一个条件(如某个表中的某个值)始终满足。如果某个数据库操作会导致这个条件不满足,那么这个操作会被拒绝。

断言可以覆盖一个或多个表,并且可以使用EXISTSNOT 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约束都会检查该行数据是否符合条件。如果不符合,操作将会被拒绝。这种方式可以有效地在数据库中强制执行数据验证规则,保持数据的完整性和准确性。


标签: none

非特殊说明,本博所有文章均为博主原创。

上一篇 Privileges in SQL
下一篇 事务与回滚

评论啦~