-- 创建测试主表. 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;
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;
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数据库系统提供了一系列的机制来帮助开发者和管理员达到这一目标,其中最重要的机制之一...
在数据库管理中,外键约束是关系数据库设计中的一个重要概念,用于维护数据的一致性和完整性。外键约束确保了引用的完整性,即一个表中的外键值必须是另一个表中存在的主键值。在进行大规模数据导入、更新或者调试时...
本课程"MLDN魔乐科技_Oracle课堂18_外键约束"深入讲解了Oracle数据库中如何利用外键来实现关系间的引用完整性。下面将详细阐述外键约束的基本原理、作用及其实现方式。 首先,外键(Foreign Key)是数据库表中的一...
下面将详细介绍如何通过SQL语句查看Oracle数据库中表的主外键约束关系。 首先,需要了解Oracle数据库中存储主外键约束信息的数据字典视图。在Oracle中,相关视图包括user_constraints、user_cons_columns等。其中,...
在本MLDN魔乐科技JAVA培训_Oracle课堂18_外键约束的课程中,我们将深入探讨这个主题,帮助Java开发者更好地理解和应用Oracle数据库中的外键约束。 首先,我们了解外键的基本概念。外键是一种特殊的字段,存在于一个...
这段代码展示了如何查询特定表(此处为“Ҫд”)的外键关联表信息,通过`p.OWNER`和`c.OWNER`确保查询的是当前用户的表,并通过`p.table_name`指定表名,通过`c.constraint_type='R'`筛选出外键约束。 2. **查询...
外键指定一个列(或一组列)的值必须符合另一个表的一些行的值。我们说这是维持关联表的参照完整性。 在图形化界面中,在 外键 选项卡,只需简单地点击外键栏位来编辑。使用外键的工具栏,能让你创建新的、编辑或...
本文将重点讨论在Oracle数据库中如何创建外键约束,同时也会提及其他类型的约束。 ### 外键约束 外键约束用于维护两个表之间的关系,确保引用完整性。在创建外键约束时,需要指定一个表中的列作为外键,它必须与另...
这行命令为 `userinfo` 表添加了一个外键约束,将 `userinfo` 表中的 `groupinfo_id` 字段与 `groupinfo` 表中的 `groupinfo_id` 字段关联起来。 #### 二、创建序列和触发器实现主键自动增长 为了实现主键的自动...
在 Oracle 中,ORA-02292 错误是由于违反了外键约束的条件,导致数据无法修改或删除。解决该错误的方法是,先修改子表中的记录,然后再修改父表中的记录。也可以使用 ALTER TABLE 语句来禁用约束,然后操作数据,...
本文将深入探讨Oracle外键不加索引引起死锁的情况,并提供解决方案。 首先,我们需要理解外键和主键的关系。在关系型数据库中,主键是表中的一个或一组列,其值唯一标识表中的每一行。外键则是另一表中指向主键的...
创建表时,可以将外键约束与字段定义一起添加,如`Create table UserInfo(StateID number constraint FK_UserInfoState references State(StateID))`。若已创建表,可使用`Alter table`添加,如`Alter table ...
例如,主键约束确保了每个用户的唯一标识,外键约束则保证了用户状态信息的有效性,非空约束确保了密码等重要信息不为空,而唯一约束可以应用于如邮箱地址等需要保证唯一性的字段。 在实际应用中,开发者需要根据...
应用于存在外键或其他约束时,需要跳过约束条件将数据导入表中,可使用该存储过程临时关闭或开启数据约束, 使用时可根据实际情况进行修改
总之,Oracle批量执行SQL语句禁用所有表的外键约束是一项实用的技巧,它能帮助你在数据导入或迁移过程中避免因外键约束导致的错误。但务必谨慎操作,并确保在操作完成后及时恢复这些约束,以保持数据库的健康状态。
5. **FOREIGN KEY约束**:用于建立表之间的引用关系,确保子表中的外键值在父表的主键或唯一键中存在。 ##### 延迟约束检查 除了上述基本约束,Oracle还支持**延迟约束检查**,允许在事务提交后检查约束,这对于...
desc + 表名 describe命令 列出指定表的列定义,视图或同义词,或指定函数或存储过程的详述。 语法:desc[ribe] {[模式.]对象...有关哪些特权允许访问不同架构中的另一个表的更多信息,请参阅Oracle数据库SQL引用。
详细介绍了oracle的常见约束,表级约束(主键),列级约束,唯一性约束,外键约束,并介绍了如何给相应的约束命名