设为首页 加入收藏

TOP

11GConcept第五章翻译DataIntegrity(数据完整性)(二)
2014-11-24 08:16:35 来源: 作者: 【 】 浏览:14
Tags:11GConcept 第五 翻译 DataIntegrity 数据 完整性
允许有重复值的列准备的。唯一键约束和主键约束不一样,主键的目的是唯一标识中表中的每一行,通常它只要求唯一,而不要求列中的值有什么意义。

使用唯一键约束的场景如下:

用户电话号码,其主键是用户编号

部门名称,其主键是部门编号

像下面例子显示,唯一键约束在employees表的email列,相关部分如下:

CREATE TABLEemployees ( ...

, 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_IDLAST_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 line1:

ORA-00001:unique constraint (HR.EMP_EMAIL_UK) violated

除非NOT NULL约束也定义了,否则NULL永远满足唯一性约束(可以插入)。因此 典型的情况是列上有唯一约束和NOT NULL约束。这种组合强制用户输入的值是唯一的,消除了新数据和已经存在数据的冲突性。

注意:根据唯一键约束在多列上的扫描机制,组合唯一键索引中,null和非null值的组合,非null值无法重复

Primary Key Constraints(主键约束)

在主键约束中,一个或多个列组合的值唯一的标识出行。每个表只能有一个主键,它的作用是命名一行,保证没有重复的行存在。

主键可以是自然值(natural)或者是专门的替代值(surrogate)。 自然键有意义的标识符,使用的是表中已经存在的列。举个例子,自然键可以是邮局表中的 邮政编码。比较起来,替代键是系统产生 自动增长的标识符,保证在这个表中 值是唯一的。

通常,替代键都是用序列生成的

Oracle数据库中主键约束保证如下:

在指定的列 或 几列,不会出现重复的值

主键列不允许出现null值

通常情况下雇员的雇员数字编号被称之为主键。每个雇员必须拥有唯一的ID号。一个雇员的情况在employees表中,必须用一行描述清楚(不能多行)。

下面例子中employee ID是主键,表中已经存在有一个ID是 202的员工

下面的案例则显示出当企图增加一个雇员 使用已经有人用了的202,或者增加主键列使用null值(不对这列进行输入值):

SQL>INSERT INTO employees (employee_id, last_name, email, hire_date, job_id)

1 VALUES (202,'Chan','ICHAN',SYSDATE,'ST_CLERK');

.

.

.

ERROR at line1:

ORA-00001:unique constraint (HR.EMP_EMP_ID_PK) violated

SQL>INSERT INTO employees (last_name) VALUES ('Chan');

.

.

.

ERROR at line1:

ORA-01400:cannot insert NULL into("HR"."EMPLOYEES"."EMPLOYEE_ID")

数据库强制主键约束要一个索引。通常,在一列上创建一个主键约束,那么会在这列隐式创建一个唯一索引 和一个NOT NULL约束。下面有一些标注了特殊情况:

在一些情况下,你会创建主键约束为延迟约束(提交后才检查),这时创建的索引是非唯一索引。

注意:你可以显示创建爱你唯一索引通过使用CREATE UNIQUE INDEX语句

当主键创建时,一个可用的索引存在,那么约束会重用这个索引,不会再隐式的创建一个新的。

默认情况下,隐式创建的索引的名称,和约束的名称一样。你同样可以自定义索引的名称。你可以在包含了ENABLE子句的CREATE TABLE或 ALTER TABLE语句中创建约束,并指定索引的存储选项。

Foreign Key Constraints(外键约束)

任何时候,两个表包含了一个或者多个相同的列,Oracle数据库可以强制保证两个表之间的关心,通过使用外键约束,也叫做 引用完整性约束。

这个约束要求在 在约束指定列上的值,必须和 引用的其他表那个列的值相匹配。

引用完整性规则的一个例子是 employee的部门编号 必须是在部门表中存在的。

下面的表列出了引用完整性约束的相关术语:

Term

Definition

Foreign key

定义在约束中的列,就是它去参考 Referenced key。举个例子,employees表的department_id列就是一个Foreign key,它引用了departments表的department_id列。

Foreign keys可以定义在多列。不管怎样,composite foreign key(组合外键)必须引用 相同数量列的组合主键或者唯一键。并且要对应的数据类型。

foreign key的值可以和应用列中的值匹配,或为null。如果组合foreign key 任意一列是null,那么这一个组合不需要匹配任何Referenced key 也能存在(所以说,foreign key列最好设not null)

Referenced key

一个唯一键或者主键。被foreign key 引用。举个例子,departments表的department_id列就是Referenced key。被employees表的departmen_id列引用。

Dependent or child table

包含foreign key的表就是子表,从属表。举个例子,employees表就是departments的子表。

Referenced or parent table

包含referenced列的表,对于子表来说,就是父表。举个例子departments表就是employees表的父表。

下图显示了在employees.department_id列的foreign key。它保证了在这列的每个值,都必须与departments.department_id列的值存在的值匹配,因此,在employees.department_id列是不会出现错误的部门号的。

\

< http://www.2cto.com/kf/ware/vc/" target="_blank" class="keylink">vcD4KPHAgYWxpZ249"left">Self-Referential Integrity Constraints(自引用完整性约束)

下面的图展示了自引用完整性约束。在这种情况下,foreign key引用的refenrencedkey在自己这个表本身。

在下面的途中,引用完整性约束保证了employees.manager_id列中的每个值,在employees.employee_id列都有存在。举个例子,雇员102 的领导,必须在雇员表中存在。这个约束保证manager_id列不会存在错误数据。

\

Null and Foreign Keys(关于外键中的null值)

foreign keys要么和referencedkey进行匹配,要么是null值

举个例子,一个用户不指定department_id 然后插入一行进入hr.employees表

组合foreign key中任何一列是null,那么都可以随便插入。

Parent KeyModifications and Foreign Keys(父键(referenced key)的修改及对Foreign Keys的影响)

父键的删除会对 foreign keys 和父键之间的关心有影响

举个例子,如果用户企图删除一个部门。那么这个部门中的雇员 会发生什么?

No action on deletion or update(对父表的更新和删除,子表没动作)

普通情况下,当父键修改后的结果违犯 关联完整性约束时,父键是无法修改的

举个例子 employees.department_id是个foreign key,关联到departments表。

如果employees表中有某个部门的行,而现在要删除departments表中的这个部门。

那就会违反这个约束,会报错。

Cascading deletions(级联删除)

级联删除指,一个包含了referenced key的行被删除,会导致子表中所有依赖的foreign key的相关行 会同时删除

举个例子:删除了departments中的一行,那么employees中的相应行也会级联删除。

Deletions that set null(父表删除,子表该列设为null值)

当父表中行删除时,则子表的对应foreign key 值设为null。

举个例子:departments表中的一行删除了,子表employees中对应的foreign key将设为null。

下面表显示了,对父表,子表的DML 分别会有什么后果

DML Statement

对于父表的影响

对于子表的影响

INSERT

如果父键(referenced key)是唯一的话,那么总是可以。

只有在外键相对应的referenced key存在这个数据是,才可以插入。或者外键就是有列值是null 也可以插入。

UPDATE NO ACTION

更新后不会对子表的行有影响时,才可以。

如果更新后的值依然有对应的父键(referenced key)时,那么可以。

DELETE NO ACTION

只有在子表中没有对应行时,才可以删除。

Always OK

DELETE CASCADE

Always OK

Always OK

DELETE SET NULL

Always OK

Always OK

注意:其他关联动作在oracle的外键完整性约束中没有支持。不过可以通过触发器自己去实现。

Indexes and Foreign Keys(索引和外键)

通常,外键要建索引。只有一种情况例外,那就是你引用的 主键或者唯一键永远都不更新,那么你可以不建。

对外键进行索引提供下面两个好处:

子表的全表锁。替代为对需要的行进行加锁。

消除对子表的全表扫描。例如,假设用户在departments中删除部门10.如果employees.department_id没有索引,那么数据库必须对employees表进行全表扫描,来看看是否有雇员的department是10

CheckConstraints(Check约束)

列或者列集的Check约束,要求表中每行,列中的值要符合这个约束,或者是null。

如果DML操作返回的结果 不符合这个约束,那么这个SQL语句会rollback

CheckConstraint最主要是可以自己定于约束的规则。举个李总,你可以使用check constraints来强制保证下面这些规则在employees表实行:

salary列的值不能有大于10000的值(太nm扣了)

commission列的值不能大于salary的值。

下面的案例在employees表上创建了一个最大salary约束,演示一下如果用户插入的值超过这个限制,会出现什么情况:

SQL> ALTERTABLE 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 line1:

ORA-02290:check constraint (HR.MAX_EMP_SAL) violated

一个列可以有多个check约束。举个例子,salary列可以有一个约束来预防值超过10000的再有一个约束来预防值小于500的。

如果多个check约束存在一列上,它们必须被合理设计,保证它们的目的不会发生冲突。多个条件的验证顺序是不一定的(不是先来后到)

数据库本身不会去验证这些条件是否是互斥的。

States of Integrity Constraints(完整性约束的状态)

作为约束定义的一部分,你可以指定oracle数据库,什么时间,以及怎样 执行约束,从而确定约束状态。

Checks forModified and Existing Data(已经存在的和新数据的检查)

数据库是你可以指定约束是应用在已经存在的数据,还是未来进入的数据。

如果约束的状态是enabled,那么数据库检查新数据(无论是插入的 还是update的)。数据不符合约束,则不能进入数据库。举个例子,employees.department_id列的NOT NULL约束是enabled的,那么它保证任何新数据都必须有department_id。

如果约束是disabled,表可以包含不符合约束的数据。

你可以将约束的状态设为验证(VALIDATE)或者不验证(NOVALIDATE)已经存在的数据。

如果指定为VALIDATE,那么存在的数据必须符合约束,举个例子,NOT NULL约束设为VALIDATE那么所在列之前已经存在的数据必须符合约束。

如果设定为NOVALIDATE,那么已经存在的数据将不需要符合约束。

VALIDATE和NOVALIDATE的行为 取决于约束是enabled还是disabled

下面的对之间的关心进行了总结:

Modified Data

Existing Data

Summary

ENABLE

VALIDATE

已经存在的和将要进入的数据必须都符合constraint,如果这个约束是新添加的,而表中的数据有不符合的,那么添加约束的操作将报错

ENABLE

NOVALIDATE

数据库对约束进行检查,但不需要符合,因此,已经存在的行可以不符合约束。但是新的或者update的数据必须符合规则

DISABLE

VALIDATE

数据库将约束禁用,删除对应索引,防止对有约束的列进行修改(不允许插入,更新删除)

DISABLE

NOVALIDATE

不检查,也不需要符合。

DeferrableConstraints(可延迟约束)

每种约束都可以是可延迟 或者不可延迟(默认),这个状态什么时候Oracle来检查约束是否符合。下面图描述了可延迟约束的选项

\

Nondeferrable Constraints(非延迟约束)

如果约束是非延迟的,Oracle数据库不会将检查延迟到事务结束。改为在每个语句结束时检查。如果约束被违反,则这个语句rollback。

举个例子,假设你创建了非延迟的NOT NULL约束。如果用户打算插入一列null值,那么数据库会立即对这条语句进行回滚,因为NOT NULL约束违反了。

DeferrableConstraints(可延迟约束)

可延迟约束允许一个事务使用SET CONSTRAINT子句来延迟约束的检查,直到COMMIT。如果你做了一些修改,它们可能违犯了约束,那么这个设置可以有效的使你暂时使约束失效,直到所有的改变完成时 再一次检查。

你可以设置当数据库对可延迟索引检查时默认的动作,你可以指定下面两种:

INITIALLY IMMEDIATE

数据库在每个语句结束时即刻检查。如果约束被违反,那么数据库回滚这条语句。

INITIALLY DEFERRED

数据库在COMMIT发布时才会检查约束,如果约束违反,那么数据库回滚这个事务。

假设可延迟约束NOT NULL在employees.last_name 列设置,且为INITIALLY DEFERRED。一个用户创建了一个事务,插入了100行,有一些行的last_name列是null值,当用户提交时,那么数据库会把这100行都回滚掉。可是,如果约束设为INITIALLY IMMEDIATE,那么数据库就不会回滚掉整个事务。

如果约束导致一个动作,那么数据库会认为这个动作是导致约束生效的这个语句的一部分,无论约束是deferred 还是immediate的。

举个例子:在departments删除一行导致了employees表的行也级联删除了。这种情况,删除employees行的这个操作会被认为是 删除departments表的DELETE语句的一部分。

Examplesof Constraint Checking(约束检查的例子)

一些例子可能会帮助你理解Oracle数据库约束检查,假设如下:

employees表自身的结构。

有一个自引用约束使得manager_id列的值引用了employee_id列的值

Insertionof a Value In a Foreign Key Column When No Parent Key Value Exists(在外键中插入数据,而这个值在父键不存在)

想象一下employees表的第一行数据的插入。现在没有行存在,那么怎样才能对manager_id进行插入呢?现在manager_id所引用的employee_id列可是没有任何值的:

null值可以插入到manager_id列,当然是没有not null 约束的情况下

因为null值是可以插入到外键中的,那么这行就插入到表里了

employee_id和manager_id列的值相同时,也可以插入。

这个案例揭示了Oracle数据库执行约束检查,是在语句完全执行运行之后。

为了在使 在父键和外键相同的情况下可以插入,数据库必须先运行语句(在这里,就是插入一个新行)然后确认表中是否有employee_id可以让新行的manager_id所匹配。

一个多行插入的INSERT语句,如INSERT 加SELECT语句,多行中如果有互相匹配的,那么就可以插入。

举个例子,插入的第一行可能employee_id是200,manager_id是300,而第二行的employee_id是300,而manager_id是200.约束会延迟到这个语句彻底完成后才去检查。

这时候,所有的行都是第一次插入,但是所有的行都通过了这个约束检查

列的default值会在语句解析前就并入到INSERT语句中。因此,默认列值是收到所有完整性约束的检查。

AnUpdate of All Foreign Key and Parent Key Values(同时了更新了所有的外键和父键的值)

考虑相同的自引用完整性约束,在一个完全不同的情况。一个公司被卖掉了,因为这个,所有的员工编号必须更新为和现在公司的员工编号一样(旧的编号加上5000)。因为经理编号,和员工编号一样(看下图),那么经理编号也必须同样的增加5000

\

你可以执行下面的语句去更新值:

UPDATE employees SET employee_id =employee_id + 5000,

manager_id = manager_id +5000;

虽然约束的定义是 每个manager_id要匹配 employee_id,但是前面的语句一样是可以成功,因为数据库实际上是在整个语句完成以后才执行检查。下图显示了数据库在执行检查之前,先执行了整个语句。

\

这些案例说明了在INSERT UPDATE时的约束的检查机制,但是数据库对于所有的DML操作都使用同样的机制,而且所有的约束都使用相同的机制,并不只是自引用完整性约束。


首页 上一页 1 2 下一页 尾页 2/2/2
】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
分享到: 
上一篇oracle禁用操作系统认证方式登陆.. 下一篇11GConcept第六章翻译DataDiction..

评论

帐  号: 密码: (新用户注册)
验 证 码:
表  情:
内  容:

·Redis on AWS:Elast (2025-12-27 04:19:30)
·在 Spring Boot 项目 (2025-12-27 04:19:27)
·使用华为开发者空间 (2025-12-27 04:19:24)
·Getting Started wit (2025-12-27 03:49:24)
·Ubuntu 上最好用的中 (2025-12-27 03:49:20)