AD JB Toolbox 01

MariaDB 강좌 / 기본키·AUTO_INCREMENT·UNIQUE로 행 식별하기

PRIMARY KEY는 테이블의 각 행을 중복 없이 식별하고, UNIQUE는 다른 업무 식별값의 중복을 막습니다. AUTO_INCREMENT는 정수 번호를 생성하는 속성이며 기본키 선언이나 빠짐없는 순번을 대신하지 않으므로, 세 기능을 필요한 조건에 맞게 함께 사용해야 합니다.

행 번호와 업무상 중복값 구분하기

고객 이름은 같은 사람이 아니어도 같을 수 있으므로 기본키로 쓰기 어렵습니다. 이 실습에서는 변하지 않는 고객 번호를 기본키로 정하고, 이메일은 별도의 중복 조건으로 다룹니다. 기본키는 행을 가리키는 기준, UNIQUE는 업무 규칙에 따라 겹치면 안 되는 값의 조건입니다.

기능 역할 조건
PRIMARY KEY 행을 식별 테이블당 하나의 기본키 정의, 구성 열은 NULL 불가·조합 중복 불가
UNIQUE 값 또는 열 조합의 중복 제한 여러 UNIQUE 정의 가능, nullable 열은 여러 NULL 허용
AUTO_INCREMENT 생략한 정수 번호를 생성 테이블당 한 열, 키로 정의 필요, 빈 번호가 생길 수 있음

기본키를 만든다는 말이 기본키 열을 하나만 써야 한다는 뜻은 아닙니다. 여러 열을 묶은 복합 기본키도 하나의 기본키 정의입니다. AUTO_INCREMENT는 반드시 PRIMARY KEY라는 규칙은 아니지만, 초보 실습에서는 단일 정수 기본키에 함께 쓰는 구성이 이해하기 쉽습니다.

고객 번호와 선택 이메일의 전체 실습

2~5강에서 준비한 course_user로 shopcourse 데이터베이스에 접속한 상태에서 실행합니다. 접속·SQL 파일 실행 방법은 명령줄 클라이언트 설명을 참고하세요. 서버 버전과 선택한 데이터베이스를 먼저 확인하고, 운영 데이터가 들어 있는 연결에서는 이 실습을 실행하지 않습니다.

SELECT VERSION() AS server_version, DATABASE() AS selected_database;
USE shopcourse;
SELECT DATABASE() AS selected_database;

customers_key_lab은 이후 고객·주문 관계를 배우기 위한 별도 연습 테이블입니다. 이메일을 아직 모르는 고객도 저장한다는 정책을 택해 email에 NULL을 허용했습니다. 기본키 열은 명시적으로 NOT NULL을 선언하고 INSERT에서는 번호를 생략합니다.

USE shopcourse;
CREATE TABLE customers_key_lab (
  customer_id INT NOT NULL AUTO_INCREMENT,
  customer_name VARCHAR(100) NOT NULL,
  email VARCHAR(254) NULL,
  PRIMARY KEY (customer_id),
  CONSTRAINT uq_customers_key_email UNIQUE (email)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
INSERT INTO customers_key_lab (customer_name, email) VALUES
  ('김민수', 'minsu@example.com'),
  ('이서연', NULL),
  ('박지우', NULL);
SELECT customer_id, customer_name, email FROM customers_key_lab ORDER BY customer_id;
CREATE TABLE product_codes_key_lab (
  supplier_id INT NOT NULL,
  supplier_code VARCHAR(30) NOT NULL,
  label VARCHAR(100) NOT NULL,
  PRIMARY KEY (supplier_id, supplier_code)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
INSERT INTO product_codes_key_lab VALUES
  (1, 'N001', '노트'),
  (2, 'N001', '다른 공급자의 노트');
SELECT supplier_id, supplier_code, label FROM product_codes_key_lab ORDER BY supplier_id;
CREATE TABLE auto_gap_lab (
  item_id INT PRIMARY KEY AUTO_INCREMENT,
  label VARCHAR(30) NOT NULL
) ENGINE=InnoDB;
START TRANSACTION;
INSERT INTO auto_gap_lab (label) VALUES ('취소할 행');
ROLLBACK;
INSERT INTO auto_gap_lab (label) VALUES ('저장한 행');
SELECT item_id, label FROM auto_gap_lab;
customer_id customer_name email
1 김민수 minsu@example.com
2 이서연 NULL
3 박지우 NULL

새 테이블의 첫 세 행 번호는 자동으로 1·2·3이 됩니다. 이름이 다른 두 고객의 이메일이 모두 NULL이어도 UNIQUE(email)에 의해 거절되지 않습니다. 이메일을 반드시 입력해야 한다면 NULL·기본값·입력 제약에서 다루는 NOT NULL도 필요하며, 이미 NULL이 있는 운영 테이블에 그 조건을 추가하기 전에는 데이터를 점검해야 합니다.

번호 생성과 제약 문법은 AUTO_INCREMENT 공식 문서와 PRIMARY KEY·UNIQUE 제약 조건 설명을 참고하세요. 이 실습에서 쓰는 example.com 이메일은 실제 발송을 위한 주소가 아니라 입력값 예시입니다.

중복 이메일과 중복 기본키를 따로 시험하기

정상 실습을 마친 뒤 아래 문장을 하나씩 실행합니다. 첫 문장은 기존 이메일과 같아 UNIQUE 오류가 발생하고, 둘째 문장은 기존 고객 번호 1을 지정해 PRIMARY KEY 오류가 발생합니다. 어떤 제약 이름이 오류에 표시되는지 비교하세요.

INSERT INTO customers_key_lab (customer_name, email) VALUES ('동명이인', 'minsu@example.com');
INSERT INTO customers_key_lab (customer_id, customer_name) VALUES (1, '중복 번호');

각 오류 뒤 SELECT COUNT(*) FROM customers_key_lab;가 3인지 확인합니다. 오류를 감추려고 INSERT IGNORE나 REPLACE로 바로 바꾸지 않습니다. REPLACE는 충돌하는 기존 행을 대체하는 동작을 포함할 수 있으므로 중복 검사의 단순한 대안이 아닙니다.

이메일 비교에는 열의 정렬 규칙이 영향을 줍니다. utf8mb4_unicode_ci에서는 대소문자를 다르게 입력해도 중복으로 판정될 수 있습니다. 실제 이메일 정책에 맞춰 정규화·비교 기준을 정하고, 저장된 글자가 다른지만 보고 UNIQUE 통과를 판단하지 않습니다.

여러 열을 묶은 복합 기본키 이해하기

두 공급자가 각각 N001이라는 상품 코드를 쓸 수 있다고 가정합니다. 상품 코드만 기본키로 정하면 두 번째 공급자의 정상 상품을 저장하지 못하므로 supplier_id와 supplier_code를 함께 묶습니다. 본문의 product_codes_key_lab은 그 조합을 기본키로 정의했습니다.

supplier_id supplier_code 중복 판단
1 N001 첫 공급자의 상품 코드
2 N001 공급자가 다르므로 다른 조합
1 N001을 다시 입력 같은 조합이므로 중복 오류
INSERT INTO product_codes_key_lab VALUES (1, 'N001', '중복 코드');

복합 기본키는 각 구성 열을 따로 중복 금지하는 것이 아니라 조합 전체를 제한합니다. 같은 supplier_id에 다른 코드, 다른 supplier_id에 같은 코드는 허용됩니다. 조회와 외래키 참조에도 열 조합이 필요할 수 있으므로 편의만 보고 열 수를 늘리지 않습니다. 실제 업무 키가 변경될 수 있다면 별도의 안정적인 번호와 UNIQUE 조합을 함께 사용하는 설계도 검토합니다.

자동 번호에 빈 구간이 생겨도 정상인 이유

전체 예제의 auto_gap_lab은 첫 INSERT를 트랜잭션에서 취소하고 두 번째 행만 저장합니다. InnoDB에서 첫 행이 예약한 번호가 ROLLBACK으로 되돌아가지 않으므로 저장된 행의 item_id는 2가 됩니다. 한 행만 있다고 번호도 반드시 1이어야 하는 것은 아닙니다.

삭제, 실패한 INSERT와 동시 작업에서도 번호가 빠질 수 있습니다. AUTO_INCREMENT를 빠짐없는 청구 번호나 행 개수로 사용하지 않습니다. SELECT COUNT(*) FROM 테이블명;이 행 개수를 확인하는 방법이며 MAX(id)는 마지막으로 보이는 번호일 뿐입니다.

방금 추가한 번호가 필요하면 같은 연결에서 성공한 INSERT 직후 LAST_INSERT_ID()를 사용할 수 있습니다. 다른 연결의 작업 결과와 섞지 않고, 실패한 INSERT 뒤 값으로 성공을 판정하지 않습니다. MAX(id)+1을 직접 계산해 새 번호로 넣으면 여러 연결이 같은 값을 선택할 수 있어 번호 생성 방식의 대안으로 적절하지 않습니다.

키 구조 확인과 반복 실습 정리

SHOW CREATE TABLE customers_key_lab;
SHOW INDEX FROM customers_key_lab;
SHOW CREATE TABLE product_codes_key_lab;

PRIMARY와 uq_customers_key_email이 별개의 키인지, 복합 기본키에 두 열이 포함되는지 확인합니다. AUTO_INCREMENT 속성과 UNIQUE 조건은 서로 다른 기능이므로 DESCRIBE의 Extra와 SHOW INDEX 결과를 함께 보는 것이 도움이 됩니다.

반복 실습 전에는 SELECT DATABASE();와 SHOW CREATE TABLE 테이블명;으로 대상이 이 강좌에서 만든 실습 테이블인지 확인합니다. 보관할 데이터가 있다면 먼저 백업합니다. 아래 명령은 지정한 테이블과 그 안의 데이터를 삭제하므로 확인한 학습용 테이블에만 실행하세요.

DROP TABLE shopcourse.customers_key_lab, shopcourse.product_codes_key_lab, shopcourse.auto_gap_lab;

삭제 후에는 본문의 전체 예제를 다시 실행할 수 있습니다. DROP TABLE 같은 데이터 정의 문장은 일반적인 트랜잭션의 ROLLBACK으로 복구할 수 있다고 기대하지 않습니다. 기존 products 테이블은 이 초기화 대상에 포함하지 않습니다.

같은 카테고리의 다른 글
MariaDB 강좌 / 데이터베이스 만들기: CREATE DATABASE·USE·문자 집합

MariaDB 강좌 / 데이터베이스 만들기: CREATE DATABASE·USE·문자 집합

shopcourse 데이터베이스를 만들고 현재 연결의 작업 대상으로 선택합니다. utf8mb4와 collation, 기존 DB에서 IF NOT EXISTS의 한계, 권한·문자 설정 확인을 예제로 설명합니다.

MariaDB 강좌 / MariaDB란? 데이터베이스·SQL·MySQL과의 관계

MariaDB 강좌 / MariaDB란? 데이터베이스·SQL·MySQL과의 관계

MariaDB 서버·클라이언트와 데이터베이스·테이블·행·열의 관계를 상품 예제로 이해합니다. SQL의 역할, MySQL과의 관계, 이후 강좌에서 사용할 실습 환경을 구분합니다.

MariaDB 강좌 / Windows에 MariaDB 설치하고 서버 실행하기

MariaDB 강좌 / Windows에 MariaDB 설치하고 서버 실행하기

Windows MSI 설치에서 서버·클라이언트, 관리자 인증, 서비스와 포트를 설정합니다. SQL 실행을 확인하고 이후 강좌에서 사용할 학습용 계정을 준비하며 시작·접속 오류를 점검합니다.

MariaDB 강좌 / NULL·기본값·NOT NULL·CHECK로 입력 조건 정하기

MariaDB 강좌 / NULL·기본값·NOT NULL·CHECK로 입력 조건 정하기

NULL·빈 문자열·0·입력 생략을 구분하고 DEFAULT·NOT NULL·CHECK의 역할을 실습합니다. nullable 열의 CHECK 예외, 실패 입력, 제약 이름과 설정 복원 방법을 설명합니다.

MariaDB / 연산자 / 논리 연산자

MariaDB / 연산자 / 논리 연산자

MariaDB의 논리 연산자에 대하여 알아보겠습니다. 예제로 사용하는 테이블은 아래의 데이터를 가진 T_2이라는 테이블입니다. 각 열의 데이터 형식은 다음과 같습니다. C_1 : 정수 C_2 : 문자 +----+------+------+ | ID | C_1 | C_2 | +----+------+------+ | 1 | 1 | A | | 2 | ...

MariaDB / Query / LEFT JOIN, RIGHT JOIN, INNER JOIN

MariaDB / Query / LEFT JOIN, RIGHT JOIN, INNER JOIN

SQL의 JOIN은 여러 테이블을 한 번에 나타낼 때 사용합니다. 대표적인 JOIN 방식은 LEFT JOIN, RIGHT JOIN, INNER JOIN이 있습니다. 다음은 세 가지 JOIN의 차이를 알아보기 위한 간단한 예제 테이블입니다.

MariaDB / 사용자 관리하는 방법

MariaDB / 사용자 관리하는 방법

MariaDB에서 사용자를 만드는 방법, 수정하는 방법, 삭제하는 방법, 권한을 부여하고 제거하는 방법을 알아봅니다.

MariaDB 강좌 / 기본키·AUTO_INCREMENT·UNIQUE로 행 식별하기

MariaDB 강좌 / 기본키·AUTO_INCREMENT·UNIQUE로 행 식별하기

기본키·자동 증가·고유 제약을 고객 데이터로 구분하고 중복 입력을 확인합니다. nullable UNIQUE, 복합 기본키와 트랜잭션 취소 후 자동 번호가 빠지는 경우를 실습합니다.

MariaDB / 데이터베이스 저장 위치 변경하는 방법

MariaDB / 데이터베이스 저장 위치 변경하는 방법

MariaDB의 버전이 12.1이라고 할 때, 윈도우용 MariaDB의 기본 설치 위치는 C:\Program Files\MariaDB 12.1, 데이터베이스 저장 위치는 C:\Program Files\MariaDB 12.1\data입니다. 데이터베이스 저장 위치를 다음으로 변경해보겠습니다. D:\Database\MariaDB\data

MariaDB 강좌 / 첫 실습: 상품 테이블을 만들고 데이터를 넣어 조회하기

MariaDB 강좌 / 첫 실습: 상품 테이블을 만들고 데이터를 넣어 조회하기

상품 세 건을 저장하는 전체 SQL로 테이블 생성·입력·조회 과정을 실습합니다. 구조와 행 수, 가격·재고 조건의 예상 결과를 확인하고 반복 입력 오류와 실습 테이블 초기화 범위를 구분합니다.