본문 바로가기
C.W.K.
Stream
Lesson 02 of 10 · published

FK (켜!)

~12 min · foreign-keys, constraints, writes

Level 0Scout
0 XP0/80 lessons0/10 achievements
0/120 XP to next level120 XP to go0% complete

기본값은 OFF야 — 직접 켜야 해

SQLite도 FK를 지원해. 그런데 예전 버전과의 호환 때문에 기본이 꺼짐이야. 그리고 connection마다 따로 켜야 해.

PRAGMA foreign_keys = ON;

이게 가장 흔한 SQLite 사고야. schema는 FK 선언을 얌전히 받아주고 다이어그램도 멀쩡해 보이는데, FK를 어기는 insert가 조용히 성공해. 엔진이 검사를 안 하니까. 피파를 포함해서 SQLite를 쓰는 프레임워크는 전부 새 connection을 열 때마다 이 PRAGMA를 돌려.

Warning: PRAGMA foreign_keys는 connection 단위지 DB 단위가 아니야. 모든 connection의 첫 statement로 넣어. connection pool을 쓴다면 connect_args나 접속 직후 콜백에서 챙겨야 해.

켜고 나면 FK가 이렇게 움직여.

  • parent 테이블에 짝이 없는 FK 값을 넣으려 하면 막아.
  • child를 미아로 만드는 parent 삭제도 막아. ON DELETE CASCADE 같은 걸 따로 지정하지 않았다면.
  • 원하면 update나 delete를 타고 내려가게 만들 수도 있어. w07에서 다뤄.

Code

켜고 동작 확인·sql
PRAGMA foreign_keys = ON;

CREATE TABLE authors (id INTEGER PRIMARY KEY, name TEXT) STRICT;
CREATE TABLE posts (
  id INTEGER PRIMARY KEY,
  author_id INTEGER NOT NULL REFERENCES authors(id),
  title TEXT NOT NULL
) STRICT;

INSERT INTO posts(author_id, title) VALUES (999, 'Orphan');
-- Error: FOREIGN KEY constraint failed
Python — 모든 connection에 PRAGMA·python
import sqlite3

def connect(path: str) -> sqlite3.Connection:
    conn = sqlite3.connect(path)
    conn.execute('PRAGMA foreign_keys = ON')
    conn.execute('PRAGMA journal_mode = WAL')
    return conn

External links

Exercise

새 DB에 authors와 posts를 만들고 FK를 선언해. PRAGMA를 켜기 전에 미아 row를 하나 넣어봐. 성공하는 걸 눈으로 봐야 해. 그다음 PRAGMA를 켜고 다시 시도해봐. 마지막으로, 코드 경로 하나에서 이 PRAGMA를 빠뜨리면 production에서 어떤 종류의 버그가 생기는지 문서로 남겨.

Progress

Progress is local-only — sign in to sync across devices.
이 페이지에서 버그를 발견하셨거나 피드백이 있으세요?문제 신고

댓글 0

🔔 답글 알림 (로그인 필요)
로그인댓글을 남기려면 로그인해 주세요.

아직 댓글이 없어요. 첫 댓글을 남겨보세요.