AD JB Toolbox 01

MariaDB 강좌 / ALTER TABLE로 구조 변경하기: 열·제약 조건·변경 전 점검

ALTER TABLE은 기존 테이블의 열·타입·제약 조건 등 구조를 바꾸는 명령입니다. 기존 데이터가 새 규칙을 만족하는지 먼저 검사하고, 새 열 추가·데이터 채우기·제약 적용을 단계적으로 진행해야 실패나 정보 손실을 줄일 수 있습니다.

구조 변경 전에 현재 정의와 복구 계획 남기기

운영 구조 변경은 이름만 바꾸는 편집이 아닙니다. 열 타입 축소·NOT NULL·UNIQUE를 적용하면 기존 행 때문에 실패하거나 값이 변환될 수 있습니다. SHOW CREATE TABLE과 데이터 백업, 사용하는 프로그램의 열 의존 관계를 확인하고 별도 환경에서 먼저 재현합니다. 추가할 조건의 뜻은 NULL·기본값·NOT NULL·CHECK로 입력 조건 정하기에서 먼저 정하고, 손실 가능성이 있는 구조 변경의 복구 자료는 mariadb-dump로 데이터베이스 백업하기처럼 별도로 준비합니다.

변경 사전 검사 위험
NOT NULL 추가 NULL 개수 기존 NULL 처리 정책 필요
UNIQUE 추가 중복 그룹 중복 정리 없으면 실패
문자열 길이 축소 최대 문자 길이 잘림·오류 가능
열 삭제 의존 쿼리·보관 필요성 저장 데이터 제거

기존 상품 행이 있는 연습 테이블 준비하기

학습용 MariaDB 서버의 shopcourse에 course_user로 접속합니다. 명령줄 클라이언트와 UTF-8 SQL 파일 실행 방법대로 코드를 UTF-8 파일에 저장하고 SOURCE C:/mariadb-lab/lesson.sql;처럼 실제 파일 경로로 실행할 수 있습니다. SQL 문은 운영체제 터미널이 아닌 MariaDB 연결 안에서 실행합니다.

먼저 SELECT VERSION(), DATABASE();와 SHOW TABLES;로 대상 서버·DB·이름 중복을 확인합니다. 아래 products_38_lab는 이 글의 독립된 연습용 이름입니다. 이미 존재하면 정의와 행을 확인하고, 보관할 자료가 없는 이 글의 실습 테이블임이 확실할 때만 마지막 절의 정리 순서로 지운 뒤 다시 만듭니다. 기존 강좌의 동명 없는 테이블이나 운영 데이터는 삭제하지 않습니다.

USE shopcourse;
CREATE TABLE products_38_lab (
  product_id INT NOT NULL AUTO_INCREMENT,
  product_name VARCHAR(100) NOT NULL,
  category VARCHAR(30) NOT NULL,
  price DECIMAL(10,2) NOT NULL,
  stock INT NOT NULL DEFAULT 0,
  note VARCHAR(100) NULL DEFAULT NULL,
  PRIMARY KEY (product_id),
  CONSTRAINT ck_p38_price CHECK (price >= 0),
  CONSTRAINT ck_p38_stock CHECK (stock >= 0)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
INSERT INTO products_38_lab (product_id,product_name,category,price,stock,note) VALUES (1, '노트', '문구', 3500.00, 20, NULL),
  (2, '볼펜', '문구', 1500.00, 0, ''),
  (3, '머그컵', '생활', 8000.00, 12, '선물 포장'),
  (4, '스탠드', '생활', 25000.00, 5, NULL),
  (5, '파일', '문구', 1500.00, 50, ''),
  (6, '케이블', '전자', 8000.00, 0, '호환 확인');

모든 상품에 새 코드 sku를 추가한다는 상황을 가정합니다. 기존 데이터에 값을 먼저 채울 수 있도록 처음에는 NULL을 허용합니다. 이 코드는 실습용 규칙이며 실제 코드 체계의 길이·불변성·고유 범위는 업무에서 정해야 합니다.

새 열 추가와 기존 데이터 채우기를 분리하기

SHOW CREATE TABLE products_38_lab;
ALTER TABLE products_38_lab ADD COLUMN sku VARCHAR(20) NULL;
UPDATE products_38_lab SET sku=CONCAT('P',LPAD(product_id,3,'0'))
WHERE sku IS NULL;
SELECT COUNT(*) AS rows_total,COUNT(sku) AS known_sku,
 COUNT(DISTINCT sku) AS unique_sku FROM products_38_lab;

새 열은 여섯 기존 행에서 처음 NULL입니다. UPDATE가 P001~P006을 채운 뒤 rows_total·known_sku·unique_sku는 모두 6이어야 합니다. 값이 비어 있거나 중복되었다면 다음 제약 적용으로 넘어가지 말고 먼저 입력 정책과 데이터를 바로잡습니다.

ALTER와 UPDATE를 하나의 ROLLBACK 가능한 묶음으로 착각하지 않습니다. 구조 작업은 암묵적 확정 등 별도 규칙을 가지므로 각 단계의 성공 상태를 기록하고, 중간에 중단되었을 때 이어 할지 복원할지 결정할 수 있어야 합니다.

NOT NULL·UNIQUE·CHECK 적용 후 실제 실패 검사하기

ALTER TABLE products_38_lab
 MODIFY COLUMN sku VARCHAR(20) NOT NULL,
 ADD CONSTRAINT uq_p38_sku UNIQUE(sku),
 ADD CONSTRAINT ck_p38_name CHECK(CHAR_LENGTH(product_name)>0);
SHOW CREATE TABLE products_38_lab;
SELECT product_id,product_name,sku FROM products_38_lab ORDER BY product_id;

sku는 NULL을 허용하지 않고 중복도 막으며 상품명 길이는 0보다 커야 합니다. MODIFY에는 보존할 타입·길이·NULL·기본값·속성을 실제 정의와 비교해 명시합니다. 일부 속성을 생략해도 언제나 그대로 남는다고 가정하지 않습니다. ALTER TABLE의 열·제약 변경 문법을 확인하세요.

별도 문장으로 상품 2의 sku를 P001로 바꾸면 UNIQUE 오류가 예상됩니다. 실패 후 기본키·원래 sku를 조회해 P002가 유지되는지 확인합니다. 빈 상품명 입력도 CHECK가 적용되는지 확인하되, 검사 설정을 끄는 방식으로 통과시키지 않습니다.

UPDATE products_38_lab SET sku='P001' WHERE product_id=2;

잠금·온라인 변경·시간 비용을 판단하기

같은 ALTER라도 버전·엔진·변경 종류·테이블 크기에 따라 내부 복사나 잠금이 필요할 수 있습니다. ALGORITHM·LOCK 옵션을 임의로 지정했다고 모든 변경이 무중단으로 가능한 것은 아닙니다. 실제 버전에서 지원하는 조합과 실패 동작, 애플리케이션의 잠금 대기까지 확인합니다.

긴 트랜잭션이 메타데이터 잠금을 잡고 있으면 ALTER가 대기할 수 있습니다. 작은 연습 테이블에서 빨리 끝난 시간으로 운영 소요 시간을 예측하지 말고 데이터량·인덱스·디스크·복구 시간을 포함해 검토합니다. 필요하면 유지보수 창과 점진적 호환 배포를 계획합니다.

원상복구의 의미와 정리 확인하기

새 열을 DROP하는 것은 그 열에 쌓인 데이터를 없애는 것이므로 원래 데이터 복구와 같지 않습니다. 손실이 가능한 변경은 이전 백업과 복원 절차가 필요합니다. 이 실습에서는 원본 여섯 상품의 이름·가격·재고가 보존되었는지 확인한 후 전용 테이블을 정리합니다.

반복하기 전 현재 DB와 실제 정의·행을 확인하고 필요한 자료를 백업합니다. 보관할 데이터가 없는 이 글의 전용 실습 객체만 아래 순서로 정리합니다. 외래키가 있으면 자식부터 지웁니다. DROP TABLE은 구조와 데이터를 모두 없애며 일반적인 ROLLBACK으로 복원되지 않으므로 취소 가능한 DML 실습과 분리합니다.

DROP TABLE shopcourse.products_38_lab;
같은 카테고리의 다른 글
MariaDB 강좌 / 이벤트 스케줄러로 정기 작업 실행하고 결과 확인하기

MariaDB 강좌 / 이벤트 스케줄러로 정기 작업 실행하고 결과 확인하기

비활성 일회성 이벤트를 생성한 뒤 미래 시각으로 활성화하고 결과 행과 예약 메타정보를 대조합니다. 반복 작업의 중복·겹침 위험, 권한·시간대 점검과 안전한 중지·정리 방법도 설명합니다.

MariaDB 강좌 / UPDATE·DELETE를 실행하기 전 대상 행 확인하기

MariaDB 강좌 / UPDATE·DELETE를 실행하기 전 대상 행 확인하기

UPDATE·DELETE 전에 기본키와 현재값으로 대상 행을 확인하고, InnoDB 트랜잭션에서 수정·삭제 결과를 검증한 뒤 취소합니다. 영향받은 행 수와 ROLLBACK의 적용 한계도 설명합니다.

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 강좌 / 첫 실습: 상품 테이블을 만들고 데이터를 넣어 조회하기

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

MariaDB 강좌 / 인덱스 만들기: 단일·복합 인덱스와 열 순서

MariaDB 강좌 / 인덱스 만들기: 단일·복합 인덱스와 열 순서

기존 키를 조회한 뒤 고객·날짜 복합 인덱스를 만들고 같은 조회 결과를 확인합니다. 열 순서·범위·커버링, 쓰기 비용·중복 키·외래키 지원 인덱스의 주의점을 설명합니다.

MariaDB 강좌 / NULL을 올바르게 비교하기: IS NULL·COALESCE

MariaDB 강좌 / NULL을 올바르게 비교하기: IS NULL·COALESCE

NULL·빈 문자열·0을 구분하고 IS NULL·IS NOT NULL과 COALESCE의 역할을 실습합니다. 일반 비교에서 빠지는 NULL 행, NULL-safe 비교와 NOT IN 목록의 함정을 설명합니다.

MariaDB 강좌 / UNION·UNION ALL로 조회 결과 합치기

MariaDB 강좌 / UNION·UNION ALL로 조회 결과 합치기

UNION과 UNION ALL을 겹치는 서울 고객·결제 고객 목록으로 비교합니다. 출처 열이 중복 기준을 바꾸는 이유, 열 위치·타입·전체 정렬의 조건을 설명합니다.

MariaDB 강좌 / 복제 구조와 지연·오류·장애 대응 이해하기

MariaDB 강좌 / 복제 구조와 지연·오류·장애 대응 이해하기

빈 두 서버를 준비하는 로컬 Compose 구성과 복제 상태·지연·오류 진단을 설명합니다. 적용 중지·재개를 관찰하고 백업과 장애 승격의 경계를 구분합니다.

MariaDB 강좌 / Python에서 MariaDB 연결하고 매개변수 쿼리 사용하기

MariaDB 강좌 / Python에서 MariaDB 연결하고 매개변수 쿼리 사용하기

PyMySQL로 연결·삽입·조회·확정·취소를 수행하는 전체 Python 예제를 제공합니다. 따옴표·한글 입력과 SQL 인젝션 형태의 문자열을 값으로 다루고 정렬 열은 허용 목록으로 제한합니다.

MariaDB 강좌 / 문자열 타입 선택하기: CHAR·VARCHAR·TEXT

MariaDB 강좌 / 문자열 타입 선택하기: CHAR·VARCHAR·TEXT

CHAR·VARCHAR·TEXT를 저장 목적에 따라 선택하고 문자 수·바이트 수·끝 공백을 비교합니다. 한글과 이모지 입력, 길이 초과 오류, 정렬 규칙과 긴 본문 저장 시 주의점을 설명합니다.