一个诡异的SQL事务现象

今天测试过程中,同事提出了一个,看似诡异,实则很基础的问题,乍一看会被迷惑。

用实验来复现下这个问题,

(1) 创建测试表,A表的id字段是主键,B表的id_a字段是外键,参考A表的id主键,

(2) 应用有这么一个逻辑,一个事务中,先更新表A,再INSERT表B,其中表B的id_a字段值是来自于表A刚才操作的主键,模拟如下,

可以看出,更新表A的操作正常,但使用表A的主键值id=1,来INSERT表B的时候,报了FK_B_A外键完整性约束的错误。

明明A表有id=1的记录,并且更新UPDATE操作成功了,为什么用id_a=1来INSERT表B,提示了外键完整性约束错误,其含义就是无法从主表找出字表要INSERT的外键值id=1,两者相矛盾么?

此处为分割线,朋友们可以思考下,为什么会有这种问题?


使用log miner利器,挖掘下redo日志,发现这张表曾经做过rename操作,

此时检索下约束信息,表B的外键约束FK_B_A,即ID_A字段,参考引用的是约束PK_A,

记得没错的话,PK_A是表A的主键字段id,可实际上,约束PK_A是表A_BAK表的主键字段列id,

原因就是之前rename了表A为表A_BAK,虽然表名变了,但表上的约束名称未变,因此表B的外键参考的表名,从表A变为了表A_BAK。

如果此时删除A_BAK可以么?

报错的原因是因为有子表参考引用了这张表的唯一键/主键,和删除数据相同,必须从子表开始操作,关系干净了,然后才能操作主表。

啰嗦几句,这里使用了drop,其实11g下这些对象并为真正删除,而是放入了回收站,

可以看出,表B、表A_BAK以及表A_BAK的主键索引,这些对象名均被改写了。

约束名称也同时被改了,

不变的则是表的字段列,

如果不想存回收站了,直接删除,则可以使用purge属性。

总结:

1. 凡是有主外键约束的表,无论删除数据还是删除表,均需要从子表开始,所有子表清理干净了,才能继续操作主表数据。

2. 任何看似诡异的现象背后,都有他存在的原因,即哲学所说的“存在即合理”。

如果您觉得此篇文章对您有帮助,欢迎关注微信公众号:bisal的个人杂货铺,您的支持是对我最大的鼓励!共同学习,共同进步:)

时间: 2024-10-26 20:22:46

一个诡异的SQL事务现象的相关文章

[译] SQL 事务隔离实用指南

本文讲的是[译] SQL 事务隔离实用指南, 原文地址:Practical Guide to SQL Transaction Isolation 原文作者:Joe Nelson 译文出自:掘金翻译计划 本文永久链接:github.com/xitu/gold-m- 译者:sigoden 校对者:mnikn, tmpbook 你可能已经在你的数据库文档中看到过隔离级别这一个概念,虽然感到有点不安,但是并没有太放在心上.一些日常的例子中使用到的事务本质上是隔离.大多数人使用数据库的的默认隔离级别,并期

WCF技术剖析之三十二:一步步创建一个完整的分布式事务应用

在完成了对于WCF事务编程(<上篇>.<中篇>.<下篇>)的介绍后,本篇文章将提供一个完整的分布式事务的WCF服务应用,通过本例,读者不仅仅会了解到如何编程实现事务型服务,还会获得其他相关的知识,比如DTC和AS-AT的配置等.本例还是沿用贯通本章的应用场景:银行转帐.我们将会创建一个BankingService服务,并将其中的转帐操作定义成事务型操作.我们先从物理部署的角度来了解一下BankingService服务,以及需要实现怎样的分布式事务. 一.从部署的角度看分

sql 事务日志传输

原文:sql 事务日志传输 概述        可以使用日志传送将事务日志不间断地从一个数据库(主数据库)发送到另一个数据库(辅助数据库).不间断地备份主数据库中的事务日志,然后将它们复制并还原到辅助数据库,这将使辅助数据库与主数据库基本保持同步.目标服务器充当备份服务器,并可以将查询处理从主服务器重新分配到一个或多个只读的辅助服务器.日志传送可与使用完整或大容量日志恢复模式的数据库一起使用:使用日志传送,您可以自动将"主服务器"实例上"主数据库"内的事务日志备份发

sql事务(Transaction)用法介绍及回滚实例

当对多个表进行更新的时候,某条执行失败.为了保持数据的完整性,需要使用事务回滚. 显示设置事务  代码如下 复制代码 begin try begin transaction insert into shiwu (asd) values ('aasdasda'); commit transaction end try begin catch select ERROR_NUMBER() as errornumber rollback transaction end catch 隐式设置事务  代码如

SQL—— 事务

原文:SQL-- 事务  SQL 事务:   1.  定义:  事务是作为单个逻辑单元执行的一系列操作. 多个操作作为一个整体向系统提交,要么执行.要么都不执行,事务是一个不可分割的工作逻辑单元.这特别适用于多用户同时操作的数据通信系统.例如:订票.银行.保险公司以及证券交易系统等.   2. 事务必须具备的特性:     1) 原子性:  Atomicity  :事务是一个完整的操作, 个元素是不可再分的.事务中所以元素必须作为一个整体提交或回滚.如果十五中任何元素失败,则整个事务将失败.  

游戏-求网络设置大神一个诡异的问题。。。。

问题描述 求网络设置大神一个诡异的问题.... 本人同一台笔记本,为什么在公司登陆游戏就卡住,回到家就可以正常进入游戏,很流畅的玩,网上说的改mtu值也改了,但是在公司登陆的时候仍然卡住进不了游戏,请问有木有懂电脑的大神指导下到底哪里的问题....我感觉跟mtu值没有关系,倒腾好几天了.跪求解答!!!! 补充:1.家里公司都是无线网.ip设置是自动获取. 2.都是10兆网络,特意下载了几个东西试了下跟网速无关. 3公司跟家里都是联通的网 解决方案 公司的socket端口封了吧 解决方案二: 试试

解决一个.NET联接SQL的问题 yiyang(转贴)

解决一个.NET联接SQL的问题    yiyang(转贴)    关键字     .NET   出处     http://Ouynagouyang    Imports System.DataImports System.Data.SqlClientImports System.Data.SqlClient.SqlExceptionPublic Class connect    Private s As String    Private s1 As String    Public Con

c语言-C语言中位运算的一个诡异问题

问题描述 C语言中位运算的一个诡异问题 #include<stdio.h> #include<math.h> #include<stdlib.h> #include<string.h> int main() { unsigned short x,n; unsigned short mask; scanf("%hu%hu",&x,&n); mask = (~0>> n); printf("%x"

写一个解析函数:SQL布尔表达式的求值

问题描述 写一个解析函数:SQL布尔表达式的求值 编写条件语句解析方法: 已知一个单条件判断方式:boolean compareItem(String fieldName, String operation, String operValue): 实现一个SQL解析函数,要求: 支持and.or: 支持括号: 支持引号: 字段名使用前缀$标识. 输入语句如:($size >= 500 and ($type != "类 型 12 3" or 0 <= $checked)) 其