Oracle存储过程update受外键约束的主键值时完整性冲突解决方案

1.问题背景

虽然在数据库操作中我们并不提倡修改主键,但是确实在实际生活中有这样的业务需求:

表A有主键KA,表B中声明了一个references A(KA)的外键约束,我们需要修改A中某条目KA的值并且更新B中外键约束。

但是DBMS在执行了第一条update后检查完整性会发现冲突:B中条目的外键不存在

注:我在Oracle database环境下遇到这个问题的,Oracle很蛋疼的不能设置外键为update级连,所以只有人工处理。

2.举例说明

用一个简单的例子说明,数据库中有以下三个表:

(1)学生表,属性有学号(主键)、姓名和年龄:

create table Student(S# integer primary key, sname varchar2(20), age integer);

(2)课程表,属性有课程号(主键)、课程名和学分:

create table Course(C# integer primary key, cname varchar2(20), credit integer);

(3)成绩表,属性有学号、课程号和分数,学号是学生表中学号外键、课程号是课程表中课程号外键:

create table SC (
       S# integer foreign key (S#) references Student(S#) on delete cascade
       C# integer foreign key (C#) references Course(C#) on delete cascade
       score integer
);

我们需要修改一个学生的学号,如果成绩表中存在改学生的成绩条目,那么就会引发上述完整性冲突。

3.解决方案

我想到的思路有两个:

  • 屏蔽(或删除)SC表外键约束,修改Student表学号,并且在保证一致性(我们DBA来保证)的情况下更新所有SC中该学生的学号,最后恢复(或添加)SC表外键约束。
  • 取出SC中所有该学生的成绩条目放在零时表/外部变量中然后删除SC中的这些记录,修改Student表学号,并且在保证一致性(同样我们DBA保证)的情况下修改零时表/外部变量中数据后再全部插入SC表。

前一个方法(屏蔽修改再恢复)比较简单,下面进一步讲解步骤:

  1. 我们需要修改以下SC表中外键声明,添加外键约束的名字,以方便我们后续屏蔽和恢复外键约束:
create table SC (
       S# integer,
       C# integer,
       score integer,
       constraint sidfk foreign key (S#) references Student(S#) on delete cascade,
       constraint cidfk foreign key (C#) references Course(C#) on delete cascade
);

这里两个外键分别命名为sidfk和cidfk。

2. 屏蔽和开启外键约束:

用SQL alter table语句实现屏蔽和开启,设S#_new是新学号,S#_old是老学号:

alter table SC disable constraint sidfk;
update Student set S# = S#_new where S# = S#_old;
update SC set S# = S#_new where S# = S#_old;
alter table SC enable constraint sidfk;

3.在Oracle上用存储过程实现

由于Oracle存储过程中不能直接使用create table或者alter table一类修改表结构的语句,需用execute immediate + SQL Command动态调用。

完整的存储过程如下:

create or replace procedure ChangeStuId(S#_old in integer, S#_new in integer)
       as
begin
        execute immediate ‘alter table SC disable constraint sidfk‘;
        update Student set S# = S#_new where S# = S#_old;
        update SC set S# = S#_new where S# = S#_old;
        execute immediate ‘alter table SC enable constraint sidfk‘;
end;
时间: 2024-10-10 15:56:00

Oracle存储过程update受外键约束的主键值时完整性冲突解决方案的相关文章

Oracle数据库,非空约束、主键约束、外键约束、唯一约束

非空约束:设置列时,可为空默认可为空,去掉对号之后设置数据不可为空: 唯一约束:在键中设置,唯一约束名称.类型Unique.列名:设置应用完成之后,此列数据具有唯一性:即数据不可重复 主键约束:主键列自动具有非空约束和唯一约束,一个表只能有一个主键约束(自动生成索引,提高查询效率)

约束(主键、非空、唯一性、外键、检查约束)

一.五种约束 如果DML操作所涉及数据违反了已定义的约束,则数据库系统将拒绝执行这样的操作. Oracle数据库中,约束具体包括非空(NOT NULL)约束.唯一键(UNIQUE)约束.主键(PRIMARY KEY)约束.外键(FOREIGN KEY)约束和检查(CHECK)约束五种. 和数据表类似,约束也属于数据库对象,可以在建表的同时创建其相关约束,也可以在建表后单独添加:可以由用户命名,也可以由系统按照默认格式自动对约束进行命名:按照约束的定义位置,又可以分为表级约束和字段级约束两种. 建

Oracle里count(1)、count(*)和count(主键)哪个更快

这两天听了将近20场演讲,感觉收获很多,最深的感觉就是自己还有很长的路要走.有几个点记录一下: 昨天听老猫讲,提到一个普遍的问题就是Oracle里count(*).count(1)和count(主键)到底哪个快的问题.这个问题看起来很简单,每个人都会有自己的答案,去百度上搜会出来一大堆帖子来讲哪个更快.但是老猫说了它们三个其实是一样的,我听到之后也觉得挺诧异的,因为我记得别人跟我说过count(主键)会快,然后自己简单想了一下,觉得好像是那么回事的就没有深入去追究.接着老猫说官方有这样的说法这三

Oracle使用游标为所有用户表添加主键语句

应用场合:数据表新增自增一主键能加快数据表的访问速度,而且是整形的索引速度最快.本程序适合在导入Oracle数据库时删除不存在主键的情况下运行. 代码说明:所有的表主键字段名都设置为ID,如果已存在ID字段,则判断是否是整形,如果不是就重命名字段为[表名ID],然后新增ID,如果不存在则直接添加自增一ID的主键 操作说明:打开PQSQL连接数据库后直接执行下面的详细脚本代码运行即可,脚本有风险(会删除原来的索引跟主键约束),请不要轻易在正式运行的数据库上直接执行 --Oracle使用游标为所有用

主键,外键,自然主键,代理主键,关系型数据库及非关系型数据库

关系型数据库: 将复杂的数据结构转换为一个二维表格即利用关系模型把数据组织到一个二维数据表,通过SQL即结构化查询语句去操作数据:后期学习Jpa面向对象查询语句jpql语句操作数据 Oracle Oracle(甲骨文/神域) 运行稳定,可移植性高,功能齐全,性能超群!适用于大型企业领域.对企业收费. DB2 IBM 速度快.可靠性好,适于海量数据,恢复性极强.适用于大中型企业领域. SQL SERVER 微软 全面,效率高,界面友好,操作容易,但是不跨平台.适用于于中小型企业领域. MYSQL

外键关联非主键id时-hbm.xml配置,及其分页查询DaoImpl

表关联时,外键关联非主键id时-hbm.xml配置: (由于hibernate默认为关联主键查询,故需要配置相关hql语句的属性) <many-to-one name="areas" class="com.hnqy.entity.Areas" fetch="select" property-ref="areaid" foreign-key="areaid"> <column name=&q

笔记:oracle关于使用代理主键还是逻辑主键的好?

总结几点体会: 第一点:统一. 最近参与的项目,其公共模块(单位表.人员信息表等)全部使用的是代理主键,而集成进来的数据模型又使用的是逻辑主键.为了最大限度的使用已经写好的存储过程.函数等对象,公共模块的数据必须按照一定规则映射一份到集成进来的模块中,这就增加了数据库维护的工作量和难度:java程序使用的持久层是hibernate,在设计javabean的时候也要考虑这种情况,是的java程序员在处理单位信息的时候不得不建立2各javabean,还需要在java程序中进行手动转换,非常耗时. 针

oracle创建表并添加主键,设置主键自增长

oracle序列详解和创建自增主键 Oracle序列主键 序列: 是oacle提供的用于产生一系列唯一数字的数据库对象. l 自动提供唯一的数值 l 共享对象 l 主要用于提供主键值 l 将序列值装入内存可以提高访问效率 1.首先创建序列,Oracle序列的语法格式为: CREATE SEQUENCE 序列名 [INCREMENT BY n] [START WITH n] [{MAXVALUE/ MINVALUEn|NOMAXVALUE}] [{CYCLE|NOCYCLE}] [{CACHE n

Oracle 主键、联合主键的查询与创建

--查询某个表是否有唯一主键 select cu.* from user_cons_columns cu, user_constraints au where cu.constraint_name = au.constraint_name and au.constraint_type = 'P' and au.table_name ='表名' --查询某个表是否有联合主键 select cu.* from user_cons_columns cu, user_constraints au whe