是否可以在 FOREIGN KEY 的子表中插入行?
Posted
技术标签:
【中文标题】是否可以在 FOREIGN KEY 的子表中插入行?【英文标题】:Is it possible to insert row into the child table of FOREIGN KEY? 【发布时间】:2019-01-06 21:59:58 【问题描述】:我的数据库中有三个表:
COMPANY(ID, NAME)
COUPON(ID, TITLE)
COMPANY_COUPON(COMPANY_ID, COUPON_ID)
公司可以创建优惠券,因此在创建优惠券时,会将优惠券的ID和公司ID添加到COMPANY_COUPON
表中。当公司删除优惠券时,由于FOREIGN KEY
,它也会从COUPON
和COMPANY_COUPON
中删除。当我删除公司时,由于FOREIGN KEY
,它也从COMPANY
和COMPANY_COUPON
中删除,但它的所有优惠券都留在COUPON
表中,我试图添加到COUPON
表FOREIGN KEY(ID) REFERENCES COMPANY_COUPON(COUPON_ID)
,但因为它我无法将新优惠券插入COUPON
表中。
很高兴回答如何创建正确的表格以及如何添加有助于现有表格的内容。 也许一些join可以帮助它,我真的不擅长sql命令,对不起......
另外,我正在使用这种方法将COMPANY_ID
和COUPON_ID
加入COMPANY_COUPON
表中,也许有更好的方法。
@Override
public void linkCompanyCoupon(long companyID, long couponID) throws CouponSystemException
Connection connection = pool.getConnection();
String CREATE_COUPON = "INSERT INTO COMPANY_COUPON (COMPANY_ID, COUPON_ID) VALUES (?,?)";
try (PreparedStatement pstmt = connection.prepareStatement(CREATE_COUPON))
pstmt.setLong(1, companyID);
pstmt.setLong(2, couponID);
pstmt.executeUpdate();
catch (SQLException e)
throw new CouponSystemException("Linking company to the coupon is failed. ", e);
finally
pool.returnConnection(connection);
这个是创建优惠券,里面我用linkCompanyCoupon();
public void createCoupon(Coupon coupon) throws CouponSystemException
// Checking if name of the new coupon is not duplicate
Optional<Coupon> isCouponTitleDuplicate = Optional.ofNullable(couponDBDAO.getCouponByTitle(coupon.getTitle()));
if (!isCouponTitleDuplicate.isPresent())
couponDBDAO.createCoupon(coupon);
companyDBDAO.linkCompanyCoupon(loggedCompany, couponDBDAO.getCouponByTitle(coupon.getTitle()).getId());
else
throw new CouponSystemException("Coupon title: " + coupon.getTitle()
+ " already exists in database, titles and IDs of the coupons must be unique.");
【问题讨论】:
COMPANY_COUPON
表有什么意义?如果每张优惠券属于一家公司,只需在表COUPON
中存储对COMPANY.ID
的引用。
是的,每张优惠券都属于一个公司,你能解释一下怎么做吗?或者您的意思只是向包含 COMPANY_ID 的 COUPON 表添加新字段?
【参考方案1】:
您的数据库设计未针对您的用例正确规范化。侯有一个一对N的关系,每个公司可以有多个优惠券,每个优惠券属于一个公司。您不需要表COMPANY_COUPON
来表示该关系。正确的做法是将COMPANY.ID
的引用存储在表COUPON
中。
ALTER TABLE coupon
ADD company_id INT NOT NULL DEFAULT 0;
ALTER TABLE coupon
ADD CONSTRAINT fk_company_id FOREIGN KEY (company_id)
REFERENCES company(id)
ON DELETE CASCADE;
【讨论】:
其实它是规范化的,它只是针对商业模式错误地规范化。 @GMB 做得很好,非常感谢!你能解释一下它们是什么:DEFAULT 0、CONSTRAINT 和 fk_?我怎样才能在创建表(第二个警报)上添加这个? @VladimirKraykin 有很多描述mysql外键的文档:试试w3school或the official mysql doc @GMB 我不会问是否没有先检查,但有时更容易理解某人的世界而不是学术文学语言。但我不坚持,我真的很感谢你回答我,因为这对我有帮助。【参考方案2】:您设置的是多对多关系:一个公司可以有很多优惠券,但一张优惠券也可以属于多个公司。这就是为什么在删除 COMPANY 时级联删除会删除连接表 (COMPANY_COUPON) 中的条目,但不会删除 COUPON 中的任何行,因为这些行也可能与其他公司相关。如果一张优惠券只能属于一家公司,那么您需要一个一对多的关系:在 COUPON 中放置一个company_id
外键列并去掉连接表。
【讨论】:
以上是关于是否可以在 FOREIGN KEY 的子表中插入行?的主要内容,如果未能解决你的问题,请参考以下文章
如何将嵌套的子表值与父表行关联并插入子表值对应于php中的父表行