UNIQUE 제약조건

sobaman·2025년 1월 29일

DB & SQL

목록 보기
3/7

UNIQUE


데이터의 무결성을 보장하기 위한 DB 칼럼의 제약 조건으로 ,

해당 열에 중복된 값이 허용되지 않도록 보장해준다.

Null


UNIQUE 제약은 알 수 없음이나 , 데이터 없음을 의미하는 NULL 값을 허용한다

UNIQUE 제약이 적용된 칼럼에서는 여러 개의 NULL 값이 허용되지만 NULL 은 고유의 값으로 간주되지 않는다

즉 NULL 은 중복으로 간주되지 않는다

왜 사용하는가?


어플리케이션 레벨에서 검증 로직이 들어가도 중복 데이터를 100% 방지할 수 없기 때문에

DB 레벨에서도 제약조건을 걸어줄 필요성이 있다.

또한 UNIQUE 제약을 설정하면 인덱스가 생성되어 성능상 이점도 얻어갈 수 있다.

단일 칼럼 유니크


단일 칼럼에 UNIQUE 제약 조건을 거는 방법은 다음과 같다

  1. DB 에서
CREATE TABLE users (
    id BIGINT PRIMARY KEY,
    email VARCHAR(255) UNIQUE
);
  1. 어플리케이션에서
@Entity
public class Member {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @Column(unique = true, nullable = false)
    private String email; // 유니크 제약 조건 적용
}

다중 칼럼 유니크 (복합 유니크 제약)


여러 칼럼을 조합하여 유니크하게 보장하기 위해 사용하는 방법

예를 들어

Member 하나가 Post 하나에 Like를 한번만 하게끔 보장하여야 할 때

둘을 조합하여 다중 칼럼 UNIQUE 제약을 설정하는 식으로 해결할 수 있다.

  1. DB 에서
CREATE TABLE likes (
    id BIGINT PRIMARY KEY AUTO_INCREMENT,
    member_id BIGINT NOT NULL,
    post_id BIGINT NOT NULL,
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    CONSTRAINT uq_member_post UNIQUE (member_id, post_id), <- 다중 칼럼 유니크 적용
    FOREIGN KEY (member_id) REFERENCES member(id) ON DELETE CASCADE,
    FOREIGN KEY (post_id) REFERENCES post(id) ON DELETE CASCADE
}
  1. 어플리케이션에서
@Entity
@Table(name = "likes", uniqueConstraints = {
    @UniqueConstraint(name = "uq_member_post", columnNames = {"member_id", "post_id"})
}) <- 다중 칼럼 유니크 적용
public class LikeEntity {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @ManyToOne
    @JoinColumn(name = "member_id", nullable = false)
    private Member member;

    @ManyToOne
    @JoinColumn(name = "post_id", nullable = false)
    private Post post;

    private LocalDateTime createdAt = LocalDateTime.now();
}
  • 유니크 제약 이름을 설정하고 조합할 필드를 설정할 수 있다.

참고


  1. 인덱스는 조회의 성능을 높여주는 대신 데이터 수정 성능을 희생시킨다는 단점이 있다
    따라서 수정이 빈번하게 이뤄지는 곳에서는 인덱스 설정을 자제하고
    조회가 자주 일어나는 곳에 인덱스를 설정해주는 것이 효과적이다

  2. 로컬에서 통합테스트 하는 경우 @Table 옵션을 통해
    유니크 인덱스를 사용하여 최대한 운영 DB 와 비슷하게 테스트.
    일반 인덱스의 경우 잘 명시하지 않는데,
    그냥 명시적으로 관리하고 싶다 할 때는 걸자.
    근데 굳이?
    엔티티엔 명시적으로 적어놧어도 DB에서 수정하거나 삭제했을 경우도 있기 때문에
    명시적으로 써놔도 DB와 일치하지 않는 경우가 꽤 있다.
    그리고 운영 DB 자체를 엔티티와 완벽히 대칭하지 않는 경우가 있다.

profile
백엔드 공부 정리 블로그

0개의 댓글