설치·접속: PostgreSQL 설치와 접속
부제: 도서 카탈로그에 ISBN을 varchar로 받다가 체크섬 틀린 값이 줄줄이 들어와, 검증을 앱이 아니라 DB에서 걸고 싶을 때
CREATE EXTENSION IF NOT EXISTS isn;
CREATE TABLE books (id serial primary key, code isbn13);
INSERT INTO books(code) VALUES ('978-0-306-40615-7');
SELECT code FROM books;
code
-------------------
978-0-306-40615-7
(1 row)isbn13 타입은 입력 시 체크섬(마지막 자리 check digit)을 자동 검증하고, 출력 시 규격에 맞는 하이픈을 붙여준다. 하이픈 없이 넣어도 검증하고 다시 포매팅한다.
INSERT INTO books(code) VALUES ('9780262033848');
SELECT id, code FROM books;
id | code
----+-------------------
1 | 978-0-306-40615-7
2 | 978-0-262-03384-8
(2 rows)핵심은 체크섬이 틀린 값이 아예 안 들어간다는 것이다. 마지막 자리를 7에서 0으로 바꾼 값을 넣어보면 insert 자체가 거부된다.
INSERT INTO books(code) VALUES ('978-0-306-40615-0');
ERROR: invalid check digit for ISBN number: "978-0-306-40615-0", should be 7에러 메시지가 올바른 check digit(7)까지 알려준다. ISBN을 text로 저장하고 앱에서 정규식·모듈로 검증을 짜던 걸, 타입 하나가 대신한다. CHECK 제약으로 흉내 내려면 check digit 계산 로직을 SQL로 직접 써야 하는데, isn은 그걸 내장하고 EAN13·ISSN·UPC 등 표준별로 다 갖고 있다.
이렇게도 쓴다
대량 임포트에서 불량 레코드까지 일단 받아야 할 때 — weak 모드를 켜면 체크섬 틀린 값도 ! 마커를 달고 들어온다.
SELECT isn_weak(true);
CREATE TABLE import (id serial primary key, code isbn13);
INSERT INTO import(code) VALUES ('978-0-306-40615-0'); -- 체크섬 불량
INSERT INTO import(code) VALUES ('978-0-306-40615-7'); -- 정상
SELECT id, code, is_valid(code) AS valid FROM import;
id | code | valid
----+--------------------+-------
1 | 978-0-306-40615-7! | f
2 | 978-0-306-40615-7 | t
(2 rows)불량 행은 ! 접미사가 붙고 is_valid가 f로 잡힌다. 임포트 후 이 행만 골라 검토·수정하는 워크플로가 된다.
make_valid로 불량 행의 마커를 떼고 정상값으로 만든다 — 체크섬을 다시 계산해 확정. (조합: is_valid 필터)
UPDATE import SET code = make_valid(code) WHERE NOT is_valid(code);
SELECT id, code, is_valid(code) AS valid FROM import ORDER BY id;
-- 두 행 모두 valid = t
check digit을 모를 때 ?로 자동 계산시킨다.
SELECT '978-0-306-40615-?'::isbn13 AS autocalc;
-- 978-0-306-40615-7
EAN13·ISSN 등 다른 표준도 같은 방식으로 검증 타입을 쓴다.
SELECT '0764554891'::isbn, '2049-3630'::issn, '4006381333931'::ean13;
앱단 검증과의 경계: 실시간 폼 입력 피드백은 프런트에서 즉시 하되, "DB에 잘못된 값이 절대 없다"는 불변식은 타입으로 강제한다. 앱 검증을 우회하는 배치·수기 INSERT 경로까지 한 번에 막는 게 타입의 값어치다.
'명령어 > DB' 카테고리의 다른 글
| [PostgreSQL] seg — 오차 범위째 저장하는 측정값 구간 타입 (0) | 2026.07.22 |
|---|---|
| [PostgreSQL] citext — 대소문자 무시 타입으로 이메일 UNIQUE를 건다 (0) | 2026.07.22 |
| [PostgreSQL] jsonb_set — 문서 전체 덮어쓰기 없이 JSONB 한 필드만 갱신한다 (0) | 2026.07.22 |
| [PostgreSQL] jsonb_to_recordset — JSON 객체 배열을 관계형 행으로 펼쳐 집계한다 (0) | 2026.07.22 |
| [PostgreSQL] jsonpath 필터 — JSONB 내부에서 부등호·범위·정규식으로 검색한다 (0) | 2026.07.22 |