Oracle官方文档翻译《Database Concepts 26ai》第7章-数据完整性
7 Data Integrity(7 数据完整性)
本章说明完整性约束如何强制实施与数据库关联的业务规则,并防止将无效信息输入到表中。
- Introduction to Data Integrity(数据完整性简介)
保持数据完整性非常重要,数据完整性是指遵守由数据库管理员或应用程序开发人员确定的业务规则。 - Types of Integrity Constraints(完整性约束的类型)
Oracle AI 数据库允许您在表和列级别应用约束,以及涉及多个表的断言。 - States of Integrity Constraints and Assertions(完整性约束和断言的状态)
作为约束或断言定义的一部分,您可以指定 Oracle AI 数据库应如何以及何时强制实施约束或断言,从而确定约束或断言的状态。
另请参见
“Overview of Tables”(表概述)了解有关列和完整性约束需求的背景信息。
Introduction to Data Integrity(数据完整性简介)
保持数据完整性非常重要,数据完整性是指遵守由数据库管理员或应用程序开发人员确定的业务规则。
业务规则指定必须始终为真或必须始终为假的条件和关系。例如,每个公司都会定义自己关于薪金、员工编号、库存跟踪等方面的策略。
- Techniques for Guaranteeing Data Integrity(保证数据完整性的技术)
在设计数据库应用程序时,开发人员有几种方法来保证存储在数据库中的数据的完整性。 - Advantages of Integrity Constraints(完整性约束的优势)
完整性约束是一种模式对象,可使用 SQL 创建和删除。为了强制实施数据完整性,请尽可能使用完整性约束或断言。
Techniques for Guaranteeing Data Integrity(保证数据完整性的技术)
在设计数据库应用程序时,开发人员有几种方法来保证存储在数据库中的数据的完整性。
这些方法包括:
- 使用触发的存储数据库过程来执行业务规则
- 使用存储过程来完全控制对数据的访问
- 在数据库应用程序的代码中执行业务规则
- 使用 Oracle AI 数据库完整性约束,这是在列或对象级别定义的用于限制数据库中的值的规则
- 使用断言,这是涉及应用程序数据库表上的子查询的布尔表达式
另请参见
- “Overview of Triggers”(触发器概述)解释了触发器的目的和类型
- “Introduction to Server-Side Programming”(服务器端编程简介)解释了存储过程的用途和特性
Advantages of Integrity Constraints(完整性约束的优势)
完整性约束是一种模式对象,可使用 SQL 创建和删除。为了强制实施数据完整性,请尽可能使用完整性约束或断言。
完整性约束和断言相对于强制实施数据完整性的替代方案的优势包括:
- 声明式简易性
由于您使用 SQL 语句定义完整性约束和断言,因此在定义或更改表时不需要额外的编程。SQL 语句易于编写,并且可以消除编程错误。 - 集中化规则
完整性约束和断言是为表定义的,并存储在数据字典中。因此,所有应用程序输入的数据都必须遵守相同的完整性约束和断言。如果规则在表级别发生更改,则应用程序无需更改。此外,应用程序可以使用数据字典中的元数据立即通知用户违规情况,甚至在数据库检查 SQL 语句之前。 - 加载数据时的灵活性
您可以暂时禁用完整性约束和断言,以避免在加载大量数据时产生性能开销。当数据加载完成后,您可以重新启用完整性约束和断言。
另请参见
- “Overview of the Data Dictionary”(数据字典概述)
- 《Oracle AI Database Get Started with Oracle AI Database Development》(《Oracle AI 数据库 Oracle AI 数据库开发入门》)和《Oracle AI Database Development Guide》(《Oracle AI 数据库开发指南》)了解如何维护数据完整性
- 《Oracle AI Database Administrator’s Guide》(《Oracle AI 数据库管理员指南》)了解如何管理完整性约束
Types of Integrity Constraints(完整性约束的类型)
Oracle AI 数据库允许您在表和列级别应用约束,以及涉及多个表的断言。
指定为列或属性定义一部分的约束是内联规范。指定为表定义一部分的约束是外联规范。
键是包含在某些类型的完整性约束定义中的列或列集。键描述关系数据库中表和列之间的关系。键中的各个值称为键值。
下表描述了约束的类型。除 NOT NULL 约束(必须内联指定)外,每种约束都可以内联或外联指定。
表 7-1 完整性约束的类型
| 约束类型(Constraint Type) | 描述(Description) | 另请参见(See Also) |
|---|---|---|
| NOT NULL | 允许或禁止插入或更新在指定列中包含空值的行。 | “NOT NULL Integrity Constraints”(NOT NULL 完整性约束) |
| 唯一键(Unique key) | 禁止多行在同一列或列组合中具有相同的值,但允许某些值为空。 | “Unique Constraints”(唯一约束) |
| 主键(Primary key) | 结合了 NOT NULL 约束和唯一约束。它禁止多行在同一列或列组合中具有相同的值,并且禁止值为空。 | “Primary Key Constraints”(主键约束) |
| 外键(Foreign key) | 将某个列指定为外键,并在外键与主键或唯一键(称为被引用键)之间建立关系。 | “Foreign Key Constraints”(外键约束) |
| 检查(Check) | 要求数据库值遵守指定的条件。 | “Check Constraints”(检查约束) |
| REF | 规定对 REF 列中的值允许的数据操作类型,以及这些操作如何影响从属值。在对象关系数据库中,名为 REF 的内置数据类型封装了对指定对象类型的行对象的引用。REF 列上的引用完整性约束确保存在该 REF 的行对象。 | 《Oracle AI Database Object-Relational Developer’s Guide》(《Oracle AI 数据库对象关系开发人员指南》)了解 REF 约束 |
| 断言(Assertions) | 断言是涉及应用程序数据库表上的子查询的布尔表达式。断言具有约束的语义,即数据库负责在事务更改数据并提交这些更改时确保这些布尔表达式为真。 | “SQL Assertions”(SQL 断言)了解断言 |
- NOT NULL Integrity Constraints(NOT NULL 完整性约束)
NOT NULL 约束要求表的列不包含空值。空表示没有值。默认情况下,表中的所有列都允许使用空值。 - Unique Constraints(唯一约束)
唯一键约束要求列或列集中的每个值都是唯一的。表的任何行都不能在具有唯一键约束的单个列(唯一键)或列集(复合唯一键)中具有重复值。 - Primary Key Constraints(主键约束)
在主键约束中,受约束的一组一个或多个列中的值唯一标识该行。每个表可以有一个主键,它实际上为该行命名并确保不存在重复行。 - Foreign Key Constraints(外键约束)
只要两个表包含一个或多个公共列,Oracle AI 数据库就可以通过外键约束(也称为引用完整性约束)来强制实施两个表之间的关系。 - Check Constraints(检查约束)
列或列集上的检查约束要求指定的条件对于每一行都为真或未知。 - Precheckable CHECK Constraints(可预先检查的 CHECK 约束)
标记为 PRECHECK 的检查约束可以在数据库外部进行检查。 - Assertions(断言)
断言是涉及应用程序数据库表上的子查询的布尔表达式。
另请参见
- “Overview of Tables”(表概述)
- 《Oracle AI Database SQL Language Reference》(《Oracle AI 数据库 SQL 语言参考》)了解有关约束类型的更多信息
NOT NULL Integrity Constraints(NOT NULL 完整性约束)
NOT NULL 约束要求表的列不包含空值。空表示没有值。默认情况下,表中的所有列都允许使用空值。
NOT NULL 约束适用于那些不能缺少值的列。例如,hr.employees 表要求 email 列有一个值。尝试插入没有电子邮件地址的员工行会生成错误:
SQL> INSERT INTO hr.employees (employee_id, last_name) values (999, 'Smith');
.
.
.
ERROR at line 1:
ORA-01400: cannot insert NULL into ("HR"."EMPLOYEES"."EMAIL")
只有在表不包含任何行或者指定了默认值的情况下,才能添加带有 NOT NULL 约束的列。
另请参见
- 《Oracle AI Database Get Started with Oracle AI Database Development》(《Oracle AI 数据库 Oracle AI 数据库开发入门》)了解向表添加 NOT NULL 约束的示例
- 《Oracle AI Database SQL Language Reference》(《Oracle AI 数据库 SQL 语言参考》)了解使用 NOT NULL 约束的限制
- 《Oracle AI Database Development Guide》(《Oracle AI 数据库开发指南》)了解何时使用 NOT NULL 约束
Unique Constraints(唯一约束)
唯一键约束要求列或列集中的每个值都是唯一的。表的任何行都不能在具有唯一键约束的单个列(唯一键)或列集(复合唯一键)中具有重复值。
注意:术语“键”仅指在完整性约束中定义的列。由于数据库通过隐式创建或重用键列上的索引来强制实施唯一约束,因此术语“唯一键”有时被错误地用作“唯一键约束”或“唯一索引”的同义词。
唯一键约束适用于任何不允许重复值的列。唯一约束与主键约束不同,主键约束的目的是唯一地标识每个表行,并且通常包含除了唯一之外没有其他含义的值。
唯一键的示例包括:
- 客户电话号码,其中主键是客户编号
- 部门名称,其中主键是部门编号
如示例 4-1 所示,hr.employees 表的 email 列上存在一个唯一键约束。相关语句部分如下:
CREATE TABLE employees ( ...
, email VARCHAR2(25)
CONSTRAINT emp_email_nn NOT NULL ...
, CONSTRAINT emp_email_uk UNIQUE (email) ... );
emp_email_uk 约束确保没有两个员工具有相同的电子邮件地址,如下例所示:
SQL> SELECT employee_id, last_name, email FROM employees WHERE email = 'PFAY';
EMPLOYEE_ID LAST_NAME EMAIL
----------- ------------------------- -------------------------
202 Fay PFAY
SQL> INSERT INTO employees (employee_id, last_name, email, hire_date, job_id)
1 VALUES (999,'Fay','PFAY',SYSDATE,'ST_CLERK');
.
.
.
ERROR at line 1:
ORA-00001: unique constraint (HR.EMP_EMAIL_UK) violated
除非同时定义了 NOT NULL 约束,否则空值始终满足唯一键约束。因此,同时具有唯一键约束和 NOT NULL 约束的列很常见。这种组合会强制用户在唯一键中输入值,并消除新行数据与现有行数据冲突的可能性。
注意:由于多列唯一键约束的搜索机制,您不能在部分为空的复合唯一键约束的非空列中具有相同的值。
示例 7-1 唯一约束
SQL> SELECT employee_id, last_name, email FROM employees WHERE email = 'PFAY';
EMPLOYEE_ID LAST_NAME EMAIL
----------- ------------------------- -------------------------
202 Fay PFAY
SQL> INSERT INTO employees (employee_id, last_name, email, hire_date, job_id)
1 VALUES (999,'Fay','PFAY',SYSDATE,'ST_CLERK');
.
.
.
ERROR at line 1:
ORA-00001: unique constraint (HR.EMP_EMAIL_UK) violated
另请参见
- “Unique and Nonunique Indexes”(唯一索引与非唯一索引)
Primary Key Constraints(主键约束)
在主键约束中,受约束的一组一个或多个列中的值唯一标识该行。每个表可以有一个主键,它实际上为该行命名并确保不存在重复行。
主键可以是自然键或代理键。自然键是由表中现有属性组成的有意义的标识符。例如,自然键可以是查找表中的邮政编码。
相比之下,代理键是系统生成的递增标识符,可确保表内的唯一性。通常,序列或 UUID 会生成代理键。
Oracle AI 数据库对主键约束的实现保证以下语句为真:
- 没有两行在指定列或列集中具有重复值。
- 主键列不允许空值。
需要主键的典型情况是员工的数字标识符。每个员工必须具有唯一的 ID。一个员工只能由 employees 表中的一行且仅一行来描述。
“Unique Constraints”(唯一约束)中的示例表明,现有员工的员工 ID 为 202,其中员工 ID 是主键。以下示例显示尝试添加具有相同员工 ID 的员工和没有 ID 的员工:
SQL> INSERT INTO employees (employee_id, last_name, email, hire_date,
job_id)
1 VALUES (202,'Chan','JCHAN',SYSDATE,'ST_CLERK');
.
.
.
ERROR at line 1:
ORA-00001: unique constraint (HR.EMP_EMP_ID_PK) violated
SQL> INSERT INTO employees (last_name) VALUES ('Chan');
.
.
.
ERROR at line 1:
ORA-01400: cannot insert NULL into ("HR"."EMPLOYEES"."EMPLOYEE_ID")
数据库使用索引强制实施主键约束。通常,为某个列创建的主键约束会隐式创建一个唯一索引和一个 NOT NULL 约束。注意以下此规则的例外情况:
- 在某些情况下,例如当您创建带有可延迟约束的主键时,生成的索引不是唯一的。
注意:您可以使用 CREATE UNIQUE INDEX 语句显式创建唯一索引。
- 如果在创建主键约束时存在可用的索引,则该约束会重用此索引,而不会隐式创建索引。
默认情况下,隐式创建的索引的名称是主键约束的名称。您也可以为索引指定用户定义的名称。您可以通过在用于创建约束的 CREATE TABLE 或 ALTER TABLE 语句中包含 ENABLE 子句来为索引指定存储选项。
另请参见
《Oracle AI Database Get Started with Oracle AI Database Development》(《Oracle AI 数据库 Oracle AI 数据库开发入门》)和《Oracle AI Database Development Guide》(《Oracle AI 数据库开发指南》)了解如何向表添加主键约束
Foreign Key Constraints(外键约束)
只要两个表包含一个或多个公共列,Oracle AI 数据库就可以通过外键约束(也称为引用完整性约束)来强制实施两个表之间的关系。
外键约束要求对于定义了约束的列中的每个值,在另一个指定的表和列中的值必须匹配。引用完整性规则的一个示例是,员工只能为现有部门工作。
下表列出了与引用完整性约束相关的术语。
表 7-2 引用完整性约束术语
| 术语(Term) | 定义(Definition) |
|---|---|
| 外键(Foreign key) | 包含在约束定义中的列或列集,它引用被引用键。例如,employees 中的 department_id 列是引用 departments 中 department_id 列的外键。外键可以定义为多列。但是,复合外键必须引用具有相同列数和相同数据类型的复合主键或唯一键。外键的值可以匹配被引用的主键或唯一键值,也可以为空。如果复合外键的任何列为空,则该键的非空部分不必匹配父键的任何相应部分。 |
| 被引用键(Referenced key) | 被外键引用的表的唯一键或主键。例如,departments 中的 department_id 列是 employees 中 department_id 列的被引用键。 |
| 从属表或子表(Dependent or child table) | 包含外键的表。此表依赖于被引用的唯一键或主键中存在的值。例如,employees 表是 departments 的子表。 |
| 被引用表或父表(Referenced or parent table) | 被子表的外键引用的表。正是此表的被引用键决定了子表中是否允许特定的插入或更新。例如,departments 表是 employees 的父表。 |
图 7-1 显示了 employees.department_id 列上的外键。它保证此列中的每个值必须匹配 departments.department_id 列中的值。因此,employees.department_id 列中不会存在错误的部门编号。
Figure 7-1 Referential Integrity Constraints(图 7-1 引用完整性约束)
- Self-Referential Integrity Constraints(自引用完整性约束)
自引用完整性约束是引用同一个表中的父键的外键。 - Nulls and Foreign Keys(空值与外键)
关系模型允许外键的值匹配被引用的主键或唯一键值,或者为空。例如,hr.employees 中的某行可能不指定部门 ID。 - Parent Key Modifications and Foreign Keys(父键修改与外键)
外键和父键之间的关系对父键的删除有影响。例如,如果用户尝试删除某个部门的记录,那么该部门中员工的记录会发生什么? - Indexes and Foreign Keys(索引与外键)
通常,外键应该建立索引。唯一的例外是当匹配的唯一键或主键从未更新或删除时。
另请参见
《Oracle AI Database Get Started with Oracle AI Database Development》(《Oracle AI 数据库 Oracle AI 数据库开发入门》)和《Oracle AI Database Development Guide》(《Oracle AI 数据库开发指南》)了解如何向表添加外键约束
Self-Referential Integrity Constraints(自引用完整性约束)
自引用完整性约束是引用同一个表中的父键的外键。
在下图中,自引用约束确保 employees.manager_id 列中的每个值都对应 employees.employee_id 列中的现有值。例如,员工 102 的经理必须存在于 employees 表中。此约束消除了 manager_id 列中出现错误员工编号的可能性。
Figure 7-2 Single Table Referential Constraints(图 7-2 单表引用约束)
Nulls and Foreign Keys(空值与外键)
关系模型允许外键的值匹配被引用的主键或唯一键值,或者为空。例如,hr.employees 中的某行可能不指定部门 ID。
如果复合外键的任何列为空,则该键的非空部分不必匹配父键的任何相应部分。例如,一个 reservations 表可能包含针对 table_id 和 date 列的复合外键,但 table_id 为空。
Parent Key Modifications and Foreign Keys(父键修改与外键)
外键和父键之间的关系对父键的删除有影响。例如,如果用户尝试删除某个部门的记录,那么该部门中员工的记录会发生什么?
当修改父键时,引用完整性约束可以指定对子表中的从属行执行以下操作:
- 删除或更新时不执行任何操作(No action on deletion or update)
通常情况下,如果结果会违反引用完整性,则用户无法修改被引用键值。例如,如果 employees.department_id 是引用 departments 的外键,并且有员工属于特定部门,则尝试删除该部门的行会违反约束。 - 级联删除(Cascading deletions)
当包含被引用键值的行被删除时,会级联删除(DELETE CASCADE),导致子表中所有具有从属外键值的行也被删除。例如,删除 departments 中的一行会导致该部门中所有员工的行被删除。 - 删除时设置为空(Deletions that set null)
当包含被引用键值的行被删除时,会进行设置为空的删除(DELETE SET NULL),导致子表中所有具有从属外键值的行将这些值设置为空。例如,删除部门行会将此部门中员工的 department_id 列值设置为空。
表 7-3 概述了父表中键值和子表中外键值的不同引用操作所允许的 DML 语句。
表 7-3 更新和删除不执行任何操作所允许的 DML 语句
| DML 语句(DML Statement) | 针对父表发出(Issued Against Parent Table) | 针对子表发出(Issued Against Child Table) |
|---|---|---|
| INSERT | 如果父键值唯一,则始终允许 | 仅当外键值存在于父键中或部分或全部为空时才允许 |
| UPDATE NO ACTION | 如果语句不会在子表中留下任何没有引用父键值的行,则允许 | 如果新的外键值仍然引用被引用键值,则允许 |
| DELETE NO ACTION | 如果子表中没有行引用父键值,则允许 | 始终允许 |
| DELETE CASCADE | 始终允许 | 始终允许 |
| DELETE SET NULL | 始终允许 | 始终允许 |
注意:Oracle 数据库的 FOREIGN KEY 完整性约束不支持的其他引用操作可以使用数据库触发器来强制执行。请参阅“Overview of Triggers”(触发器概述)。
另请参见
《Oracle AI Database SQL Language Reference》(《Oracle AI 数据库 SQL 语言参考》)了解 ON DELETE 子句
Indexes and Foreign Keys(索引与外键)
通常,外键应该建立索引。唯一的例外是当匹配的唯一键或主键从未更新或删除时。
为子表中的外键建立索引具有以下好处:
- 防止子表上的全表锁定。相反,数据库会在索引上获取行锁。
- 无需对子表进行全表扫描。举例来说,假设用户从 departments 表中删除了部门 10 的记录。如果 employees.department_id 没有建立索引,那么数据库必须扫描 employees 表以查看部门 10 中是否存在任何员工。
另请参见
- “Locks and Foreign Keys”(锁与外键)解释了已索引和未索引外键列的锁定行为
- “Introduction to Indexes”(索引简介)解释了索引的目的和特性
Check Constraints(检查约束)
列或列集上的检查约束要求指定的条件对于每一行都为真或未知。
如果 DML 导致约束的条件求值为假,则 SQL 语句将回滚。检查约束的主要好处是能够强制实施非常具体的完整性规则。例如,您可以使用检查约束在 hr.employees 表中强制实施以下规则:
- salary 列的值不得大于 10000。
- commission 列的值不得大于薪金。
以下示例在 employees 表上创建一个最大薪金约束,并演示了当语句尝试插入包含超过最大值的薪金的行时会发生什么:
SQL> ALTER TABLE employees ADD CONSTRAINT max_emp_sal CHECK (salary < 10001);
SQL> INSERT INTO employees
(employee_id,last_name,email,hire_date,job_id,salary)
1 VALUES (999,'Green','BGREEN',SYSDATE,'ST_CLERK',20000);
.
.
.
ERROR at line 1:
ORA-02290: check constraint (HR.MAX_EMP_SAL) violated
单个列可以具有多个在其定义中引用该列的检查约束。例如,salary 列可以有一个防止值超过 10000 的约束,以及一个单独的防止值小于 500 的约束。
如果一个列存在多个检查约束,则必须设计它们的目的不冲突。不能假设条件的评估顺序。数据库不会验证检查条件是否互斥。
另请参见
《Oracle AI Database SQL Language Reference》(《Oracle AI 数据库 SQL 语言参考》)了解检查约束的限制
Precheckable CHECK Constraints(可预先检查的 CHECK 约束)
标记为 PRECHECK 的检查约束可以在数据库外部进行检查。
将检查约束设置为 PRECHECK 状态是在创建或更改表时完成的。PRECHECK 状态补充了约束的 ENABLE 和 VALIDATE 状态,您可以同时激活所有这三种状态。
如果您使用 JSON 来表示检查约束,Oracle AI 数据库允许您导出 JSON 模式,并在应用程序客户端内根据 JSON 模式验证器验证 JSON 数据。当约束设置为 PRECHECK 状态时,它表明该约束具有等效的 JSON 模式,该模式保留了约束的语义。客户端应用程序开发人员可以在客户端应用程序中预先验证约束。数据库会检查该约束,如果约束无法用 JSON 模式表示,则会生成错误。
相关主题
- 使用带有 CHECK 约束的 PRECHECK 预先验证 JSON 数据
- ALL_CONSTRAINTS
Assertions(断言)
断言是涉及应用程序数据库表上的子查询的布尔表达式。
断言具有约束的语义,即数据库负责在事务更改数据并提交这些更改时确保这些布尔表达式为真。
以下 SQL 语句创建一个名为 NO_TRAINERS_IN_BOSTON 的断言,要求波士顿的部门中不雇用任何培训师。顶层的 NOT EXISTS 表示一个布尔表达式,该表达式要求 EMP 和 DEPT 表之间连接的结果集保持为空。
CREATE ASSERTION no_trainers_in_boston CHECK
(NOT EXISTS
(SELECT 'trainer in Boston'
FROM emp e, dept d
WHERE e.deptno = d.deptno
AND e.job = 'TRAINER'
AND d.loc = 'BOSTON'));
断言是模式级别的对象。这意味着如果布尔表达式引用了其他模式的表,则需要 ASSERTION REFERENCES 对象权限才能访问这些表。这与跨两个模式的外键没有什么不同,也就是说,必须具有 REFERENCES 对象权限才能成功创建“指向”不同模式中表的主键的外键。
断言是通用的数据完整性约束。它们可用于替代 CHECK、PRIMARY KEY、UNIQUE 和 FOREIGN KEY 约束。
例如,假设 EMP 表上有以下约束:
- CHECK (COMM <= SAL)
- PRIMARY KEY (EMPNO)
- UNIQUE (ENAME, DEPTNO)
- FOREIGN KEY (DEPTNO) REFERENCES DEPT(DEPTNO)
这些约束可以用以下断言来实现:
CREATE ASSERTION commission_not_greater_than_salary CHECK
(NOT EXISTS
(SELECT ''
FROM emp e
WHERE e.comm > e.sal));
CREATE ASSERTION emp_empno_pk CHECK
(NOT EXISTS
(SELECT ''
FROM emp e1, emp e2
WHERE e1.empno = e2.empno
AND e1.rowid != e2.rowid));
CREATE ASSERTION emp_ename_deptno_uk CHECK
(NOT EXISTS
(SELECT ''
FROM emp e1, emp e2
WHERE e1.ename = e2.ename
AND e1.deptno = e2.deptno
AND e1.rowid != e2.rowid));
CREATE ASSERTION emp_fk_dept CHECK
(NOT EXISTS
(SELECT ''
FROM emp e
WHERE NOT EXISTS
(SELECT ''
FROM dept d
WHERE d.deptno = e.deptno)));
但是,我们强烈建议您尽可能始终使用约束,并且仅在无法使用约束时才使用断言。
相关主题
- 《Oracle AI Database Administrator’s Guide》(《Oracle AI 数据库管理员指南》)
- ALL_ASSERTIONS
- ALL_ASSERTION_DEPENDENCIES
- ALL_ASSERTION_LOCK_MATRIX
States of Integrity Constraints and Assertions(完整性约束和断言的状态)
作为约束或断言定义的一部分,您可以指定 Oracle AI 数据库应如何以及何时强制实施约束或断言,从而确定约束或断言的状态。
- Checks for Modified and Existing Data(对已修改数据和现有数据的检查)
数据库允许您指定约束或断言是应用于现有数据还是将来的数据。如果约束或断言已启用,则数据库会在输入或更新新数据时对其进行检查。不符合约束或断言的数据无法进入数据库。 - When the Database Checks Constraints and Assertions for Validity(数据库何时检查约束和断言的有效性)
每个约束和断言都处于不可延迟(默认)或可延迟状态。此状态决定了 Oracle AI 数据库何时检查约束或断言的有效性。 - Examples of Constraint and Assertion Checking(约束和断言检查示例)
以下示例有助于说明 Oracle AI 数据库何时执行约束和断言的检查。
Checks for Modified and Existing Data(对已修改数据和现有数据的检查)
数据库允许您指定约束或断言是应用于现有数据还是将来的数据。如果约束或断言已启用,则数据库会在输入或更新新数据时对其进行检查。不符合约束或断言的数据无法进入数据库。
例如,在 employees.department_id 上启用 NOT NULL 约束可确保将来的每一行都有一个部门 ID。如果约束被禁用,则表可以包含违反约束的行。
您可以将约束和断言设置为以下任一验证模式:
- VALIDATE(验证)
现有数据必须符合约束或断言。例如,在 employees.department_id 上启用 NOT NULL 约束并将期设置为 VALIDATE,会检查每个现有行是否都有部门 ID。 - NOVALIDATE(不验证)
现有数据不必符合约束或断言。实际上,这是一种“信任我”模式。例如,如果您确信加载到表中的每笔销售都有一个日期,则可以在日期列上创建一个 NOT NULL 约束,并将该约束设置为 NOVALIDATE。未强制实施的约束通常仅对物化视图和查询重写有用。
对于处于 NOVALIDATE 模式的约束,RELY 参数指示优化器可以使用该约束来确定连接信息。即使该约束不用于验证数据,它也能为物化视图启用更复杂的查询重写,并使数据仓库工具能够从数据字典中检索约束信息。默认值为 NORELY,这意味着优化器实际上不知道该约束。
VALIDATE 和 NOVALIDATE 的行为始终取决于约束或断言是启用还是禁用。下表总结了这些关系。
表 7-4 对已修改数据和现有数据的检查
| 已修改数据(Modified Data) | 现有数据(Existing Data) | 摘要(Summary) |
|---|---|---|
| ENABLE VALIDATE | 现有数据和将来数据都必须遵守约束或断言。尝试对已填充的表应用新约束或断言时,如果现有行违反约束或断言,则会导致错误。 | |
| ENABLE NOVALIDATE | 数据库会检查约束或断言,但它不必对所有行都为真。因此,现有行可以违反约束或断言,但新行或修改的行必须符合规则。此模式通常用于包含其完整性已验证的现有数据的数据仓库。 | |
| DISABLE VALIDATE | 数据库禁用约束,删除其索引,并禁止修改受约束的列。断言不能处于此状态。 | |
| DISABLE NOVALIDATE | 不检查约束或断言,它不一定为真。 |
另请参见
《Oracle AI Database SQL Language Reference》(《Oracle AI 数据库 SQL 语言参考》)了解约束状态
When the Database Checks Constraints and Assertions for Validity(数据库何时检查约束和断言的有效性)
每个约束和断言都处于不可延迟(默认)或可延迟状态。此状态决定了 Oracle AI 数据库何时检查约束或断言的有效性。
下图显示了可延迟约束和断言的选项。
Figure 7-3 Options for Deferrable Constraints and Assertions(图 7-3 可延迟约束和断言的选项)
- Nondeferrable Constraints and Assertions(不可延迟约束和断言)
在不可延迟约束中,Oracle AI 数据库永远不会将对约束或断言的有效性检查推迟到事务结束。相反,数据库在每个语句末尾检查约束或断言。如果违反约束或断言,则语句回滚。 - Deferrable Constraints and Assertions(可延迟约束和断言)
可延迟约束或断言允许事务使用 SET CONSTRAINT 子句将此约束或断言的检查推迟到发出 COMMIT 语句时。如果您对数据库所做的更改可能违反约束或断言,则此设置实际上使您能够在所有更改完成之前禁用该约束或断言。
Nondeferrable Constraints and Assertions(不可延迟约束和断言)
在不可延迟约束中,Oracle AI 数据库永远不会将对约束或断言的有效性检查推迟到事务结束。相反,数据库在每个语句末尾检查约束或断言。如果违反约束或断言,则语句回滚。
例如,employees.last_name 列存在一个不可延迟的 NOT NULL 约束。如果某个会话尝试插入没有姓氏的行,则数据库会立即回滚该语句,因为违反了 NOT NULL 约束。不会插入任何行。
Deferrable Constraints and Assertions(可延迟约束和断言)
可延迟约束或断言允许事务使用 SET CONSTRAINT 子句将此约束或断言的检查推迟到发出 COMMIT 语句时。如果您对数据库所做的更改可能违反约束或断言,则此设置实际上使您能够在所有更改完成之前禁用该约束或断言。
您可以设置数据库检查可延迟约束或断言的默认行为。您可以指定以下任一属性:
- INITIALLY IMMEDIATE(初始立即)
数据库在每个语句执行后立即检查约束或断言。如果违反约束或断言,则数据库回滚该语句。 - INITIALLY DEFERRED(初始延迟)
数据库在发出 COMMIT 时检查约束或断言。如果违反约束或断言,则数据库回滚事务。
假设 employees.last_name 上的可延迟 NOT NULL 约束设置为 INITIALLY DEFERRED。用户创建一个包含 100 个 INSERT 语句的事务,其中一些语句的 last_name 为空值。当用户尝试提交时,数据库会回滚所有 100 个语句。但是,如果此约束设置为 INITIALLY IMMEDIATE,则数据库不会回滚该事务。
如果某个约束导致某个操作,则数据库会将此操作视为导致该操作的语句的一部分,无论该约束是延迟的还是立即的。例如,删除 departments 中的一行会导致删除 employees 中所有引用已删除部门行的行。在这种情况下,从 employees 中的删除被视为针对 departments 执行的 DELETE 语句的一部分。
另请参见
《Oracle AI Database SQL Language Reference》(《Oracle AI 数据库 SQL 语言参考》)了解有关约束属性及其默认值的信息
Examples of Constraint and Assertion Checking(约束和断言检查示例)
以下示例有助于说明 Oracle AI 数据库何时执行约束和断言的检查。
假设如下:
- employees 表具有“Self-Referential Integrity Constraints”(自引用完整性约束)中所示的结构。
- 自引用约束使 manager_id 列中的条目依赖于 employee_id 列的值。
- Example: Insertion of a Value in a Foreign Key Column When No Parent Key Value Exists(示例:不存在父键值时在外键列中插入值)
此示例涉及将第一行插入到 employees 表中。当前不存在任何行,那么如果 manager_id 列中的值无法引用 employee_id 列中的现有值,如何输入行? - Example: Update of All Foreign Key and Parent Key Values(示例:更新所有外键和父键值)
在此示例中,自引用约束使 employees 的 manager_id 列中的条目依赖于 employee_id 列的值。 - Example: Every Manager Must Have a Clerk in the Same Department(示例:每个经理必须在同一部门中有一名办事员)
此示例创建一个断言,以确保每个经理在同一部门中都有一名办事员。
Example: Insertion of a Value in a Foreign Key Column When No Parent Key Value Exists(示例:不存在父键值时在外键列中插入值)
此示例涉及将第一行插入到 employees 表中。当前不存在任何行,那么如果 manager_id 列中的值无法引用 employee_id 列中的现有值,如何输入行?
一些可能性是:
- 如果 manager_id 列上没有定义 NOT NULL 约束,则可以为第一行的 manager_id 列输入空值。
因为外键中允许空值,所以 Oracle AI 数据库会将此行插入表中。 - 您可以在 employee_id 和 manager_id 列中输入相同的值,指定该员工是自己的经理。
这种情况表明 Oracle AI 数据库在执行语句后执行其约束检查。为了允许插入在父键和外键中具有相同值的行,数据库必须首先插入新行,然后确定表中是否有任何行的 employee_id 对应于新行的 manager_id。 - 多行 INSERT 语句(例如带有嵌套 SELECT 语句的 INSERT 语句)可以插入相互引用的行。
例如,第一行的员工 ID 可能为 200,经理 ID 为 300,而第二行的员工 ID 为 300,经理 ID 为 200。约束检查将推迟到 INSERT 语句完全执行之后。数据库插入所有行,然后检查所有行是否存在约束违规。
在解析语句之前,默认值会作为 INSERT 语句的一部分包含在内。因此,默认列值要接受所有完整性约束检查。
Example: Update of All Foreign Key and Parent Key Values(示例:更新所有外键和父键值)
在此示例中,自引用约束使 employees 的 manager_id 列中的条目依赖于 employee_id 列的值。
公司已被出售。由于此次出售,所有员工编号都必须更新为当前值加上 5000,以与新公司的员工编号协调一致。如下图所示,某些员工也是经理:
Figure 7-4 The employees Table Before Updates(图 7-4 更新前的 employees 表)
由于经理编号也是员工编号,因此经理编号也必须增加 5000。您可以执行以下 SQL 语句来更新值:
UPDATE employees SET employee_id = employee_id + 5000,
manager_id = manager_id + 5000;
尽管定义了一个约束来验证每个 manager_id 值与 employee_id 值匹配,但前面的语句是有效的,因为数据库实际上在语句完成后检查约束。图 7-5 显示数据库在执行整个 SQL 语句的操作之后才检查约束。
Figure 7-5 Constraint Checking(图 7-5 约束检查)
本节中的示例说明了 INSERT 和 UPDATE 语句期间的约束检查机制,但数据库对所有类型的 DML 语句使用相同的机制。数据库对所有类型的约束使用相同的机制,而不仅仅是自引用约束。
注意:对视图或同义词的操作受基表上定义的完整性约束的约束。
Example: Every Manager Must Have a Clerk in the Same Department(示例:每个经理必须在同一部门中有一名办事员)
此示例创建一个断言,以确保每个经理在同一部门中都有一名办事员。
此示例要求您先插入办事员,再插入经理。当执行多行插入时,与约束一样,断言会在每个 INSERT 语句执行后进行验证。您可以将此断言设置为 DEFERRABLE,以便允许您先插入经理,然后再插入办事员。验证将在 COMMIT 时进行,而不是在每个 INSERT 语句时进行。
CREATE ASSERTION manager_has_clerk check
(NOT EXISTS
(SELECT 'manager without clerk'
FROM employees m
WHERE m.job_id = 'ST_MAN'
AND NOT EXISTS
(SELECT 'a clerk in same department'
FROM employees c
WHERE c.job_id = 'ST_CLERK'
AND c.department_id = m.department_id)));
AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。
更多推荐
所有评论(0)