[플젝] 2PicGames - 장바구니 구현시 고려사항

서현서현·2022년 5월 30일
0

DB, SQL

목록 보기
25/27

1. 쟁점

💡 팀원이 미리 장바구니의 insert부를 구현했는데, 장바구니에 추가 버튼을 누를때마다 값이 계속해서 들어가게 만들어져있었다. 이전에 내가 게임Id와 사용자Id를 조합하여 구현한 위시리스트Id(기본키)와 다르게 기본키가 CART_NO(순서대로 늘어나는 함수로 구현)이기 때문에 중복되어도 오류가 나지 않았기 때문이다!

💡 여러개 넣어두고 select해올때는 하나만 가져오면 될것같다는 팀원의 의견을 따라서 insert, delete, read부를 새로 구현해보기로 했다


2. DB쿼리 설계

가정 : cart와 cart_game을 조인해서.. mem_id가 a001인 기록을 꺼내온다

문제점 : 그런데 a001이 game001을 여러번 담았을수도 있다

select시 distinct를 사용해야하나? → 혀튼 같은 게임id는 한번만 가져온다.

-- a001이 담은 모든 게임id와 그 가격을 출력
select distinct a.cart_price, b.game_id
from cart a
inner join cart_game b
on(a.CART_NO = b.CART_NO)
and a.mem_id='a001';

삭제 연산시 삭제할 내용이 있는지 테이블을 먼저 검사

[삭제연산 로직]
1. gameId에 해당하는 cartNo를 cart_game테이블에서 찾고 (gameId는 여러번 들어올수 있으니 cartNo가 여러개 선택된다)
2. cartNo에 해당하는 정보들을 Cart에서 찾고
3. innerJoin으로 연결해서 cartNo에 해당하는 모든행들을 두 테이블에서 삭제

→ a001 유저는 game001을 두번 넣어뒀으니 그걸 삭제하면 game001 두개가 전부 삭제되어야 한다는 뜻!

→ 아 근데 서로다른사람이 같은 아이디의 게임을 넣어뒀을수도 있으니 cart부터 조회해야한다(memId로 cartId를 먼저 선택해야된다는 이야기)

(방법1) 선택해서 delete 수행하는 쿼리 만들기

-- delete할 내용 선택
select *
from cart a
inner join cart_game b
on(a.CART_NO = b.CART_NO)
where a.mem_id='a001' and b.game_id='game001';

→ 근데 이걸 서브쿼리로 delete하는 방법을 모르겠다 ㅠㅠ 쿼리로 한번에 해결하지 말고 다르게 생각해보기로 하자

(방법2) 따로따로 삭제 (자식요소부터 삭제함에 유의)

우선 CART_GAME테이블부터 삭제해보자면
게임아이디와 카트넘버가 있는데, 이제 어떤 게임을 삭제할지는 아는데 어떤 멤버의것을 삭제해줘야되는지를 모름 → 따라서 멤버를 구별하기위해 cartNo를 가져와야된다. (cart와 이너조인을 하자)

select a.cart_no
from cart a
inner join cart_game b
on(a.CART_NO = b.CART_NO)
where a.mem_id='a001'and b.game_id='game001';

a001 유저가 담은 game001의 장바구니 번호 cart_no가 구해진다.
이제 이 cart_no에 해당하는 값들을 두 테이블에서 지워주면 됨!!

delete from **cart_game**
where cart_no in (
	select a.cart_no
	from cart a
	inner join cart_game b
	on(a.CART_NO = b.CART_NO)
	where a.mem_id='a001'and b.game_id='game001'
)

다음,,, cart에서도 삭제하자

delete from **cart**
where cart_no in (
	select a.cart_no
	from cart a
	inner join cart_game b
	on(a.CART_NO = b.CART_NO)
	where a.mem_id='a001'and b.game_id='game001'
)

🚨 문제 발생!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
cart_game에서 저 데이터를 삭제하면
on 조건절에서 만족하는 데이터가 없어져서 cart테이블의 데이터를 삭제할수가 없다
select로 찾은 겹치는 cart_no를 String으로 저장해뒀다가 각각 삭제연산할때 매개변수로 넣어주는 수밖에 없당

제약조건때문에 자식(cart_game)부터 삭제하는거 잊지말기!
(부모테이블의 cart를 먼저 삭제한다면 cart_game은 존재하지 않는 외래키를 참조해버린다 즉 참조무결성 제약조건 위배)

(방법3) 삭제할 cart_id를 구해서 String에 저장한뒤 두 테이블에 각각 삭제연산시키기

delete from cart_game
where cart_no = 'cart1' or cart_no = 'cart2'

delete from cart
where cart_no = 'cart1' or cart_no = 'cart2'

2-1. DB에 insert할때 중복값을 없애 문제를 원천봉쇄하자

백단 코드를 짜면서 굳이 데이터베이스에 중복 게임아이디가 여러번 들어갈 필요가 있나? 라는 생각이 들었다. 조회할때 결국 distinct로 딱 하나만 가져오게 되는것이기 떄문이다.

그래서 insert할때 아예 중복값을 없애면 되겠다는 판단이 들었다

어떻게?

그냥 조인 써서 이미 존재하는지 정보를 검사하면 될일이였다!!!!!!!!!!!!!!!!!!!!!!

풀어서 설명하자면,

만약 장바구니 insert 요청이 온다면 인서트 메소드 실행 전에 검사를 하는것!

두 테이블 이너조인 해놓고 요청의 gameId와 memId를 동시에 만족하는 cartid 찾아와서..
cartid가 존재하면 장바구니 insert실행 아니면 경고창 띄우면 된다.

단순한거였는데 이미 팀원이 구현해서 넣어놓은 데이터를 그대로 사용하려다보니 이런 상황이 발생한것같다. 앞으론 이미있는 코드를 어떻게 재활용할까도 좋지만 원래 어떤식으로 구현되는게 맞는지 큰그림을 그려놓도록 하자....!

참고로 코드는 delete할 아이디가 있는지 확인하는 쿼리 만들어 뒀던걸 재활용했다. 사실상 insert전에 확인해서 값이 없으면 insert를 하고, delete전에 검사해서 값이 있으면 delete연산을 수행하는, 값 체크 코드였다! 이걸 check로 바꿔서 두개 다 구현했더니 잘된당

이제 위시리스트나 장바구니 DB에는 중복값이 절대 들어가지 않을것이다!

0개의 댓글