`

ORACLE外键约束

 
阅读更多

-- 创建测试主表. ID 是主键.

CREATE TABLE test_main (

 id      INT,

 value   VARCHAR(10),

 PRIMARY KEY(id)  

);

 

 

-- 创建测试子表. 

CREATE TABLE test_sub (

  id      INT,

 main_id INT,

 value   VARCHAR(10),

 PRIMARY KEY(id)  

);

 

 

-- 插入测试主表数据.

INSERT INTO test_main(id, value) VALUES (1,'ONE');

INSERT INTO test_main(id, value) VALUES (2,'TWO');

 

-- 插入测试子表数据.

INSERT INTO test_sub(id, main_id, value)VALUES (1, 1, 'ONEONE');

INSERT INTO test_sub(id, main_id, value)VALUES (2, 2, 'TWOTWO');

 

 

 

默认外键约束方式

 

SQL> -- 创建外键(默认选项)

SQL> ALTER TABLE test_sub ADD CONSTRAINT main_id_cons  FOREIGN KEY (main_id)  REFERENCES test_main;

 

Table altered.

 

SQL>

SQL> -- 测试删除主表数据. 将出错 ORA-02292:违反完整约束条件

SQL> DELETE

 2    test_main

 3  WHERE

 4    ID = 1;

DELETE

*

ERROR at line 1:

ORA-02292: integrity constraint(HR.MAIN_ID_CONS) violated - child record found

 

 

测试完毕后,删除外键约束

ALTER TABLE test_subDROP CONSTRAINT main_id_cons;

 

 

 


 

 

DELETE CASCADE 方式

 

SQL> -- 创建外键(使用 ON DELETECASCADE 选项,删除主表的时候,同时删除子表)

SQL> ALTER TABLE test_sub

  2    ADDCONSTRAINT main_id_cons

  3     FOREIGN KEY (main_id) REFERENCES  test_main  ON DELETE  CASCADE;

 

Table altered.

 

SQL>

SQL> -- 测试删除主表数据. 将成功地执行.

SQL> DELETE

 2    TEST_MAIN

 3  WHERE

 4    ID = 1;

 

1 row deleted.

 

SQL>

SQL> -- 测试检索子表,应该只有一条 main_id = 2 的数据.

SQL> SELECT

 2    *

 3  FROM

 4    test_sub;

 

       ID    MAIN_ID VALUE

---------- ---------- --------------------

         2          2 TWOTWO

 

 

测试完毕后,删除外键约束 

ALTER TABLE test_sub DROP CONSTRAINT main_id_cons;

 

 

 

SET NULL方式

 

SQL> -- 创建外键(使用 ON DELETESET NULL 选项,删除主表的时候,同时将子表的 main

_id 设置为 NULL)

SQL> ALTER TABLE test_sub

  2   ADD CONSTRAINT main_id_cons

  3     FOREIGN KEY (main_id) REFERENCES  test_main  ON DELETE SET NULL;

 

Table altered.

 

SQL>

SQL>

SQL> -- 测试删除主表数据. 将成功地执行.

SQL> DELETE

 2    TEST_MAIN

 3  WHERE

 4    ID = 2;

 

1 row deleted.

 

SQL>

SQL> -- 测试检索子表,应该有一条的 main_id = null

SQL> SELECT

 2    *

 3  FROM

 4    test_sub;

 

       ID    MAIN_ID VALUE

---------- ---------- --------------------

         2            TWOTWO

 

测试完毕后,删除外键约束 

ALTER TABLE test_sub DROP CONSTRAINT main_id_cons;

 

 

 

 

 

 

启用/禁用

 

当遇到批量数据导入的时候,如果外键处于有效的状态。
那么要求 数据导入的程序, 必须先导入主表的数据,然后再导入子表的数据。
如果表多,且关系复杂的话,会增加很大的工作量。

可以在数据导入以前, 先暂时禁用外键约束。
子表、主表数据都导入完毕后, 再启用外键约束。

 

以下测试环境为 初始的创建表、初始数据的情况。

 


SQL> -- 创建外键(默认选项)
SQL> ALTER TABLE test_sub ADD CONSTRAINT main_id_cons  FOREIGN KEY (main_id)  REFERENCES  test_main;

表已更改。

SQL> -- 测试插入子表数据. 将出错 ORA-02291: 违反完整约束条件
SQL> INSERT INTO test_sub (ID, MAIN_ID, VALUE) VALUES (3, 3, 'THREETHREE');
INSERT INTO test_sub (ID, MAIN_ID, VALUE) VALUES (3, 3, 'THREETHREE')
*
ERROR 位于第 1 行:
ORA-02291: 违反完整约束条件 (TEST.MAIN_ID_CONS) - 未找到父项关键字

 

 

-- 尝试禁用外键约束.
SQL> ALTER TABLE test_sub  MODIFY   CONSTRAINT main_id_cons DISABLE;
表已更改。


SQL> INSERT INTO test_sub (ID, MAIN_ID, VALUE) VALUES (3, 3, 'THREETHREE');
已创建 1 行。

SQL> INSERT INTO test_main(id, value) VALUES (3, 'THREE');
已创建 1 行。

SQL> commit;
提交完成。

 

 

-- 恢复启用外键约束.
SQL> ALTER TABLE test_sub  MODIFY   CONSTRAINT main_id_cons  ENABLE;
表已更改。


SQL> DELETE test_main  WHERE ID = 1;
DELETE test_main  WHERE ID = 1
*
ERROR 位于第 1 行:
ORA-02292: 违反完整约束条件 (TEST.MAIN_ID_CONS) - 已找到子记录

 

 

测试完毕后,删除外键约束 

ALTER TABLE test_sub DROP CONSTRAINT main_id_cons;

 

 

 

 

延迟约束

 


在编程开发环境中,可能会遇到,要先插入子表, 然后插入主表。
或者先更新主表的 主键, 然后更新子表的外键的情况。


由于是开发环境下,因此不适合使用 先 DISABLE 再 ENABLE 的处理机制。
原因是程序中可能会存在并发处理

也就是

用户A   DISABLE -- 更新处理  -- ENABLE
用户B              DISABLE -- 更新处理  -- ENABLE


这种情况下,需要启用 延迟约束
也就是 INSERT / UPDATE 语句执行的时候, 暂时不检查数据的完整性,等到 Commit 的时候,统一做检查。

 

 

 


SQL> -- 创建外键(默认选项)
SQL> ALTER TABLE test_sub ADD CONSTRAINT main_id_cons 
  2    FOREIGN KEY (main_id)  REFERENCES  test_main 
  3    DEFERRABLE   INITIALLY DEFERRED;
表已更改。


SQL> INSERT INTO test_sub (ID, MAIN_ID, VALUE) VALUES (4, 4, 'FOURFOUR');

已创建 1 行。

SQL> commit;
commit
*
ERROR 位于第 1 行:
ORA-02091: 事务处理已回退
ORA-02291: 违反完整约束条件 (TEST.MAIN_ID_CONS) - 未找到父项关键字

 


SQL> INSERT INTO test_sub (ID, MAIN_ID, VALUE) VALUES (4, 4, 'FOURFOUR');
已创建 1 行。

SQL> INSERT INTO test_main(id, value) VALUES (4, 'FOUR');
已创建 1 行。

SQL> commit;
提交完成。

 

外键索引

啥时不需要外键索引?
Expert one-on-one Oracle中提到:

  • You do not delete from the parent table.
  • You do not update the parent tables unique/primary key value, either purposely or by accident (via a tool).

这两种情况下,没有外键索引,Oracle会锁子表,当使用ON DELETE CASCADE时,会进行全表扫描。

  • You do not join from the parent table to the child table, of more generally ‐ the foreign key columns do not support an important access path to the child table.

利用join查询时,没有外键索引,Oracle就会进行全表扫描。

当确认这些情况不会出现时,便可以不添加外键索引,但是,如何监测子表是否被锁呢?
Oracle有一个机制:
ALTER TABLE <child table name> DISABLE TABLE LOCK;
这时,UPDATE和DELETE获取锁是都会失败。

 

不从父表删除记录很难避免,因此,如果没有外键索引,将很容易导致死锁,缺外键索引是死锁的主要原因,另外,位图索引的并发更新也是可能导致死锁。

 

以下是ORACLE Database Concept上的描述,记录一下:

Indexes and Foreign Keys

As a rule, foreign keys should be indexed. The only exception is when the matching unique or primary key is never updated or deleted. Indexing the foreign keys in child

tables provides the following benefits:

■ Prevents a full table lock on the child table. Instead, the database acquires a row

lock on the index.

■ Removes the need for a full table scan of the child table. As an illustration,

assume that a user removes the record for department 10 from the departments

table. If employees.department_id is not indexed, then the database must scan

employees to see if any employees exist in department 10.

 

分享到:
评论

相关推荐

    聊聊Oracle外键约束的几个操作选项

     Oracle外键是维护参照完整性的重要手段,大多数情况下的外键都是紧密关联关系。外键约束的作用,是保证字表某个字段取值全都与另一个数据表主键字段相对应。也是说,只要外键约束存在并有效,不允许无参照取值...

    Oracle定义约束 外键约束

    ### Oracle定义约束:外键约束详解 #### 一、引言 在数据库设计与管理过程中,维护数据的一致性和完整性是非常重要的。Oracle数据库系统提供了一系列的机制来帮助开发者和管理员达到这一目标,其中最重要的机制之一...

    禁用启用所有外键约束.tst

    在数据库管理中,外键约束是关系数据库设计中的一个重要概念,用于维护数据的一致性和完整性。外键约束确保了引用的完整性,即一个表中的外键值必须是另一个表中存在的主键值。在进行大规模数据导入、更新或者调试时...

    MLDN魔乐科技_Oracle课堂18_外键约束

    本课程"MLDN魔乐科技_Oracle课堂18_外键约束"深入讲解了Oracle数据库中如何利用外键来实现关系间的引用完整性。下面将详细阐述外键约束的基本原理、作用及其实现方式。 首先,外键(Foreign Key)是数据库表中的一...

    oracle查看主外键约束关系

    下面将详细介绍如何通过SQL语句查看Oracle数据库中表的主外键约束关系。 首先,需要了解Oracle数据库中存储主外键约束信息的数据字典视图。在Oracle中,相关视图包括user_constraints、user_cons_columns等。其中,...

    MLDN魔乐科技JAVA培训_Oracle课堂18_外键约束.rar

    在本MLDN魔乐科技JAVA培训_Oracle课堂18_外键约束的课程中,我们将深入探讨这个主题,帮助Java开发者更好地理解和应用Oracle数据库中的外键约束。 首先,我们了解外键的基本概念。外键是一种特殊的字段,存在于一个...

    oracle主外键查询

    这段代码展示了如何查询特定表(此处为“Ҫд”)的外键关联表信息,通过`p.OWNER`和`c.OWNER`确保查询的是当前用户的表,并通过`p.table_name`指定表名,通过`c.constraint_type='R'`筛选出外键约束。 2. **查询...

    在Oracle数据库中添加外键约束的方法详解

    外键指定一个列(或一组列)的值必须符合另一个表的一些行的值。我们说这是维持关联表的参照完整性。 在图形化界面中,在 外键 选项卡,只需简单地点击外键栏位来编辑。使用外键的工具栏,能让你创建新的、编辑或...

    oracle中如何创建约束?

    本文将重点讨论在Oracle数据库中如何创建外键约束,同时也会提及其他类型的约束。 ### 外键约束 外键约束用于维护两个表之间的关系,确保引用完整性。在创建外键约束时,需要指定一个表中的列作为外键,它必须与另...

    oracle设置主外键即主键序列自动增长

    这行命令为 `userinfo` 表添加了一个外键约束,将 `userinfo` 表中的 `groupinfo_id` 字段与 `groupinfo` 表中的 `groupinfo_id` 字段关联起来。 #### 二、创建序列和触发器实现主键自动增长 为了实现主键的自动...

    Oracle 约束错误约束错误

    在 Oracle 中,ORA-02292 错误是由于违反了外键约束的条件,导致数据无法修改或删除。解决该错误的方法是,先修改子表中的记录,然后再修改父表中的记录。也可以使用 ALTER TABLE 语句来禁用约束,然后操作数据,...

    Oracle外键不加索引引起死锁示例

    本文将深入探讨Oracle外键不加索引引起死锁的情况,并提供解决方案。 首先,我们需要理解外键和主键的关系。在关系型数据库中,主键是表中的一个或一组列,其值唯一标识表中的每一行。外键则是另一表中指向主键的...

    Oracle所有约束基本语法

    创建表时,可以将外键约束与字段定义一起添加,如`Create table UserInfo(StateID number constraint FK_UserInfoState references State(StateID))`。若已创建表,可使用`Alter table`添加,如`Alter table ...

    oracle基本约束语法

    例如,主键约束确保了每个用户的唯一标识,外键约束则保证了用户状态信息的有效性,非空约束确保了密码等重要信息不为空,而唯一约束可以应用于如邮箱地址等需要保证唯一性的字段。 在实际应用中,开发者需要根据...

    Oracle的约束【Constraint】

    5. **FOREIGN KEY约束**:用于建立表之间的引用关系,确保子表中的外键值在父表的主键或唯一键中存在。 ##### 延迟约束检查 除了上述基本约束,Oracle还支持**延迟约束检查**,允许在事务提交后检查约束,这对于...

    建立外键约束.txt

    desc + 表名 describe命令 列出指定表的列定义,视图或同义词,或指定函数或存储过程的详述。 语法:desc[ribe] {[模式.]对象...有关哪些特权允许访问不同架构中的另一个表的更多信息,请参阅Oracle数据库SQL引用。

    Oracle 关闭所有约束 存储过程

    应用于存在外键或其他约束时,需要跳过约束条件将数据导入表中,可使用该存储过程临时关闭或开启数据约束, 使用时可根据实际情况进行修改

    oracle约束

    详细介绍了oracle的常见约束,表级约束(主键),列级约束,唯一性约束,外键约束,并介绍了如何给相应的约束命名

    MLDN魔乐科技_Oracle课堂

    Oracle课堂10Oracle课堂11_子查询Oracle课堂12_数据库更新操作Oracle课堂13_事务处理Oracle课堂14_SQL语法练习1Oracle课堂15_SQL语法练习2Oracle课堂16_表的管理Oracle课堂17_约束Oracle课堂18_外键约束Oracle课堂 ...

Global site tag (gtag.js) - Google Analytics