Можно ли вставить строку в дочернюю таблицу FOREIGN KEY? - PullRequest
0 голосов
/ 07 января 2019

В моей базе данных три таблицы:

COMPANY(ID, NAME)  
COUPON(ID, TITLE)  
COMPANY_COUPON(COMPANY_ID, COUPON_ID)

Компания может создавать купоны, поэтому при создании купона идентификатор купона и идентификатор компании будут добавлены в таблицу COMPANY_COUPON. Когда компания удаляет купон, он также будет удален из COUPON и COMPANY_COUPON из-за FOREIGN KEY. Когда я удаляю компанию, она также удаляется из COMPANY и COMPANY_COUPON из-за FOREIGN KEY, но все ее купоны остаются в таблице COUPON, я пытался добавить в COUPON таблицу FOREIGN KEY(ID) REFERENCES COMPANY_COUPON(COUPON_ID), но из-за этого я невозможно вставить новые купоны в таблицу COUPON.

Буду рад ответам о том, как создавать правильные таблицы и как добавить что-то, что поможет существующим таблицам. Может быть, некоторые объединения могут помочь с этим, я действительно еще не силен в команде 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.");
    }
}

Ответы [ 2 ]

0 голосов
/ 07 января 2019

Дизайн вашей базы данных не нормализован для вашего варианта использования. У вас есть отношение «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;
0 голосов
/ 07 января 2019

То, что вы установили, это отношения «многие ко многим»: у компании может быть много купонов, но купон также может принадлежать многим компаниям. Вот почему каскадное удаление удаляет записи в объединяющей таблице (COMPANY_COUPON) при удалении COMPANY, но не удаляет строки в COUPON, поскольку эти строки также могут быть связаны с какой-либо другой компанией. Если купон может принадлежать только одной компании, то вам нужно отношение один ко многим: поместите столбец внешнего ключа company_id в COUPON и избавьтесь от таблицы объединения.

...