mySQL 중복되지 않는 것만 INSERT하기

이상진·2022년 6월 27일
0

상황

사용자의 방문기록을 남기는 작업을 하던 중에
사용자가 오늘 방문했다면 한번만 기록을 남겨주면 되는 상황에 중복으로 INSERT가 들어가지 않기 위해서 쿼리문을 작성해보았습니다.

해결방법

여러가지 방법이 있겠지만
크게 나눠 보면
DB작업을 통해 해결하는 방법과
쿼리문으로 해결하는 방법입니다.

다만 위에 상황에서 사용자가 방문했을때 오늘은 1번만 기록해준다는 상황에서는 DB로 작업을 하는게 맞지 않아보였습니다.

DB를 바꿔서 해결

DB로 작업하는 방법을 먼저 살펴보면...
1. 중복되면 안되는 컬럼 조합을 primary key나 unique index로 설정
2. on duplicate key를 이용하는 방법
등이 있습니다.

1번에서는

ALTER TABLE PAGE_LOG ADD PRIMARY KEY (USER_ID, REG_DATE)

혹은

ALTER TABLE PAGE_LOG ADD UNIQUE INDEX (USER_ID, REG_DATE)

이 방법은
간단한 INSERT문을 위해서 KEY를 변경하는게 썩 내키지 않았습니다.
또 그렇게되면 쿼리문이 실행될때마다 오류가 뜨게 됩니다.

2번에서 on duplicate key를 사용하는 방법 역시 key를 설정해야하기 떄문에 마찬가지로 제외 했습니다.

INSERT INTO PAGE_LOG (USER_ID, REG_DATE)
VALUES (userId, now())
ON DUPLICATE KEY [처리할 쿼리문]

쿼리문으로 해결하는 방법

결국 제가 선택한 방법은
Insert문에 WHERE NOT EXISTS를 추가하는 방법입니다.

INSERT
  INTO PAGE_LOG
(
  USER_ID, REG_DATE
)
VALUES
(
  userId, DATE_FORMAT(now(), '%Y-%m-%d')    // 1
)
WHERE NOT EXISTS(SELECT *
				   FROM PAGE_LOG
                  WHERE USER_ID = userId
                    AND REG_DATE = DATE_FORMAT(now(), '%Y-%m-%d')

// 1 : DATE_FORMAT은 날짜까지만 나오도록 설정했습니다.

처음에 위처럼 쿼리문을 작성했는데 계속 에러가 났습니다.

계속 고민하다가 이리저리 알아보니
VALUES 부분을 SELECT FROM dual 로 바꿔주니까 해결되었습니다.

💡최종 쿼리문

최종 쿼리문은...

INSERT
      INTO PAGE_LOG
    (
      USER_ID, REG_DATE
    )
	SELECT 'userId', date_format(now(), '%Y-%m-%d') FROM dual
	WHERE NOT EXISTS (SELECT * 
    					FROM PAGE_LOG 
                       WHERE USER_ID = 'userId' 
                         AND REG_DATE = date_format(now(), '%Y-%m-%d')
	);

제가 설정한 예시가 헷갈리실 수 있어서 밑에 정리해 두었습니다.

INSERT
      INTO [테이블명]
    (
      [컬럼명1, 컬럼명2]
    )
	SELECT [컬럼명1에 넣을 내용, 컬럼명2에 넣을 내용] FROM dual
	WHERE NOT EXISTS (SELECT * 
    					FROM [테이블명] 
                       WHERE [컬럼명1] = [컬럼명1에 넣을 내용] 
                         AND [컬럼명2] = [컬럼명2에 넣을 내용]
	);

핵심은 SELECT ... FROM dual을 해줘야 정상작동 된다는 점입니다.

profile
Back-end Engineer

0개의 댓글