본문 바로가기
TIL with Programmers

[TIL] 10/10 장바구니 기능 구현, SQL 에러

by 보먀 2024. 10. 10.
728x90
반응형

1. SQL 에러

 

1.1. ERROR 1005: Can't create table `book-shop`.`new_table` (errno: 121 "Duplicate key on write or update")

 

새롭게 만든 cartItems 테이블에 FK 제약 조건을 설정해주려고 했는데 에러가 났다.

이 에러는 이미 존재하는 제약조건의 이름을 또 사용하려고 했을 때 발생하는 에러이기 때문에, 제약 조건의 이름을 바꿔주면 에러가 나지 않는다. 

 

이런 에러를 방지하기 위해 제약조건의 이름도 규칙에 따라 지을 수 있다. 

fk_기준 테이블명_참조테이블명_참조키

 

앞에 fk 제약 조건을 표시하기 위해 fk 를 붙이고, 기준 테이블명 참조테이블명을 차례로 써 준 뒤에 참조하는 키의 컬럼명을 써주면 된다. 

 

예시를 들어보자면, 아래와 같이 지으면 된다. 

 

cartItems 테이블의 user_id 가 users 테이블의 id 를 참조하는 경우: fk_cartItems_users_id

likes 테이블의 user_id 가 users 테이블의 id 를 참조하는 경우: fk_likes_users_id

 

 

1.2. ERROR 1061: Duplicate key name 

 

fk 제약 조건의 이름을 바꿔주니 ERROR 1061: Duplicate key name 라는 새로운 에러가 발생했다. 

이 에러는 같은 이름의 인덱스나 키를 두 번 정의하려고 할 때 발생하는 에러인데, 나의 경우 같은 이름의 인덱스가 존재해서 에러가 났다. 

 

book_id_idx, user_id_idx 라는 인덱스가 이미 존재하는 이름이어서 에러가 난 것이기 때문에 인덱스 이름 앞에 테이블 이름을 붙여 에러가 나지 않도록 고쳐주었더니 에러가 나지 않았다. 

 

book_id_idx -> cartItems_book_id_idx 

user_id_idx -> cartItems_user_id_idx 

 

 

 

2. 장바구니 API 구현

 

2.1. 장바구니 담기

// CartController.js
const addToCart = (req, res) => {
    // 장바구니 담기
    const {book_id, quantity, user_id} = req.body;

    let sql = `INSERT INTO cartItems (book_id, quantity, user_id) VALUES (?, ?, ?)`;
    let values = [book_id, quantity, user_id];
    conn.query(sql, values,
        (err, results) => {
            if (err) {
                console.log(err);
                return res.staus(StatusCodes.BAD_REQUEST).end();
            }
            res.status(StatusCodes.OK).json(results);
        }
    )
};

 

 

2.2. 장바구니 목록 조회

// CartController.js
const getCartItems = (req, res) => {
    const {user_id} = req.body;

    let sql = `SELECT cartItems.id, book_id, title, summary, quantity, price FROM cartItems LEFT JOIN books ON cartItems.book_id = books.id WHERE user_id = ?`;
    conn.query(sql, user_id,
        (err, results) => {
            if (err) {
                console.log(err);
                return res.staus(StatusCodes.BAD_REQUEST).end();
            }
            res.status(StatusCodes.OK).json(results);
        }
    )
};

 

 

2.3. 장바구니 아이템 삭제

// CartController.js
const removeCartItem = (req, res) => {
    // 장바구니 아이템 삭제
    const {id} = req.params;

    let sql = `DELETE FROM cartItems WHERE id = ?`;
    conn.query(sql, id,
        (err, results) => {
            if (err) {
                console.log(err);
                return res.status(StatusCodes.BAD_REQUEST).end();
            }
            res.status(StatusCodes.OK).json(results);
        }
    )
};

 

 

2.4. 장바구니에서 선택한 아이템 목록 조회

 

일부 상품만 선택

 

장바구니에 여러 상품이 담겨있을 때, 일부 상품만 골라서 결제하는 상황이 있을 수 있는데, 이때 장바구니 전체 목록에서 선택한 일부 상품만 조회하는 API 를 만들려고 한다. 근데 생각해보면, 장바구니에 담은 전체 상품을 조회하는 API 를 살짝만 고치면 장바구니에서 선택한 상품만을 조회할 수 있기 때문에 기존의 코드를 고쳐서 사용하려고 한다. 

 

selected 라는 배열에 선택한 상품의 id 값을 담아서 보낼 수 있는데, request body 에 selected 가 담겨오면 선택한 장바구니 상품 목록 죄회를 담겨오지 않으면 장바구니 전체 아이템 목록 조회를 할 수 있도록 만들었다.

  • request body 에 user_id, selected 배열을 담아서 보냄 -> 장바구니에서 선택한 상품 목록 조회
  • request body 에 user_id 만 담아서 보냄 -> 장바구니 전체 목록 조회
// CartController.js
const getCartItems = (req, res) => {
    // 장바구니 아이템 목록 조회 & 선택한 장바구니 상품 목록 조회
    const {user_id, selected} = req.body;

    let sql = `SELECT cartItems.id, book_id, title, summary, quantity, price 
                FROM cartItems LEFT JOIN books 
                ON cartItems.book_id = books.id 
                WHERE user_id = ?`;
    let values = [user_id];
    
    if (selected) {
        sql += 'AND cartItems.id IN (?)';
        values.push(selected);
    }

    conn.query(sql, values,
        (err, results) => {
            if (err) {
                console.log(err);
                return res.status(StatusCodes.BAD_REQUEST).end();
            }
            res.status(StatusCodes.OK).json(results);
        }
    )
};

 

sql 쿼리문을 살펴보자.

 

출력할 컬럼들 고르기

 

SELECT cartItems.id, book_id, title, summary, quantity, price

 

cartItems 테이블과 books 테이블을 cartItems.book_id = books.id 의 조건으로 조인하기

FROM cartItems LEFT JOIN books ON cartItems.book_id = books.id

 

user_id 가 ? 이고 cartItems.id 값이 ?(배열) 조건일 때

WHERE user_id = ? AND cartItems.id IN (?)

 

여기서 IN 은 특정 조건을 만족하는 여러 값을 비교할 때 사용하는 연산자로 (...) 괄호 안에 들어가는 여러 값들 중 하나인 모든 행을 조회한다. 

 

 

728x90
반응형