前言
这是错误是数据库的相关操作过程中出现的。在一个名为购物商城的项目中,处理交易数据时,做了一个测试方法,这个测试方法执行后出现的异常。
描述
INSERT INTO tradeitem(bookid,quantity,tradeid) VALUES(1,2,25)
(2)作用:将该信息插入交易历史记录表tradeItem 中。
(3)异常:
执行测试方法后抛出异常如下:
Cannot add or update a child row: a foreign key constraint fails
(`bookstore`.`tradeitem`, CONSTRAINT `trade_id_fk` FOREIGN KEY (`tradeid`) REFERENCES `trade` (`tradeid`))
Query: INSERT INTO tradeitem(bookid,quantity,tradeid) VALUES(?,?,?)
Parameters: [[1, 10, 25], [2, 20, 25], [3, 30, 25], [4, 40, 25], [5, 50, 25]]
分析
1.表trade 与tradeItem 的设计
<1>表的描述
(1)trade:交易信息表。例如某userid 为1 的用户在2017-4-1 做了一次交易,tradeid 作为主键自动生成。
- tradeid:交易id
- userid:用户id
- tradetime:交易时间
(2)tradeItem:交易历史表。例如一次交易有唯一的tradeid,此交易下交易详细可对应tradeItem 表中一条及以上个记录。一次交易中可以包括不同的书购买了不同的数量。
- itemid:交易记录id
- bookid:图书id
- quantity:购买数量
- tradeid:交易id
图1.表设计图
<2>表记录截图
图2.表trade 记录图
图3.表tradeItem 记录图
<3>异常分析
异常提示插入或更新对应数据表tradeItem 失败。
原因是因为外键的问题。因为交易表trade 和交易记录表tradeItem 中存在外键tradeid
该字段是trade 表的主键,同时也是tradeItem 表的外键。
重点就在这层关系上。tradeid 不是独立的字段。当我在测试方法中模拟一次图书商城的交易后,向交易记录中更新插入此次交易记录信息。模拟数据没有考虑到tradeid 这层关系
INSERT INTO tradeitem(bookid,quantity,tradeid) VALUES(1,2,25)
可以看到最新的交易是2017-4-5 日id 为1 的用户进行了一次交易。交易编号目前更新到21 号,不存在25 对应的交易。
测试方法:是测试插入交易历史记录的,所以直接初始化了一些交易数据并没有将此次交易对应更新到trade 表中,直接进行插入tradeItem 表。导致tradeid 外键不可为25 而出现的异常。
处理
1.处理操作
将25 改为12-21 之间的数据即可。即外键tradeid 数据必须在表trade 中存在。
2.说明
事实上在该项目上一般不会出现此问题。因为项目运行过程中,执行一次交易之后会实时更新trade 表中的信息,对应产生最新的交易信息:即用户id 为多少的用户在某个时刻进行了交易,交易编号作为主键自动对应生成。验证此次交易成功后,才会执行插入交易记录,即向表tradeItem 中更新信息。此时tradeid 是不会出错的。