Python 강좌 / sqlite3로 데이터 저장하고 매개변수 쿼리 사용하기

sqlite3는 별도 데이터베이스 서버 없이 파일에 SQL 데이터를 저장하는 Python 표준 모듈입니다. 입력값은 SQL 문자열에 직접 넣지 않고 매개변수로 전달하고, 트랜잭션의 성공·실패 시점을 명확히 관리합니다.

SQLite와 연결·트랜잭션

SQLite는 프로그램에 포함해 사용하는 데이터베이스 엔진입니다. 파일 하나로 시작하기 편하지만 여러 쓰기 요청을 처리하는 방식과 운영 조건은 서버형 DB와 다릅니다. sqlite3 연결을 여는 것만으로 모든 작업이 영구 저장되지는 않습니다.

관련 동작과 지원 조건은 sqlite3로 데이터 저장하고 매개변수 쿼리 사용하기 관련 공식 문서에서 확인할 수 있습니다.

예제는 Python 3.12 이상에서 autocommit=False를 명시하여 트랜잭션 제어 방식을 고정합니다. with connection은 성공 시 commit, 예외 시 rollback을 수행하지만 연결 자체를 닫지는 않으므로 finally에서 close합니다.

전체 예제와 실행 결과

별도의 실습 폴더에서 아래 파일을 UTF-8로 저장합니다. 가상환경을 선택한 터미널에서 python sqlite_demo.py 명령으로 실행합니다. macOS·Ubuntu에서 가상환경을 사용하지 않는 경우 명령 이름을 python3으로 바꿉니다.

sqlite_demo.py 파일의 전체 내용입니다.

import sqlite3

con = sqlite3.connect("ledger-demo.db", autocommit=False)
try:
    with con:
        con.execute("CREATE TABLE IF NOT EXISTS expenses (id TEXT PRIMARY KEY, name TEXT NOT NULL, amount INTEGER NOT NULL CHECK(amount >= 0))")
        con.execute("INSERT INTO expenses VALUES (?, ?, ?) ON CONFLICT(id) DO UPDATE SET name=excluded.name, amount=excluded.amount", ("e1", "lunch", 8000))
    rows = con.execute("SELECT name, amount FROM expenses ORDER BY id").fetchall()
    print(rows)
finally:
    con.close()

예상 결과는 다음과 같습니다.

[('lunch', 8000)]

매개변수와 데이터 제약

물음표는 값 자리이며 execute의 두 번째 인수로 튜플을 전달합니다. 값 하나인 튜플은 (value,)처럼 쉼표가 필요합니다. 테이블명·정렬 열 같은 SQL 구조는 값 매개변수로 바꿀 수 없으므로 필요한 경우 허용 목록에서 선택합니다.

NOT NULL·PRIMARY KEY·CHECK는 저장소에서도 규칙을 적용합니다. Python에서 검증하더라도 다른 입력 경로를 대비해 DB 제약을 함께 사용합니다. 재실행 예제는 같은 id를 갱신하므로 같은 지출이 계속 추가되지 않습니다.

실패·재실행·연결 정리 확인하기

  1. 같은 파일을 두 번 실행해 행이 하나인지 확인합니다.
  2. 금액을 음수로 바꾸면 DB 제약이 실패하고 기존 값이 남는지 확인합니다.
  3. 다른 id로 한 건 더 저장해 ORDER BY에 따른 순서를 확인합니다.

SELECT에 ORDER BY가 없으면 조회 순서를 전제로 하지 않습니다. 파일 잠금 오류가 나면 다른 연결의 긴 트랜잭션과 연결 종료 여부를 확인합니다. 실제 업무 파일을 초기화하는 DROP TABLE을 예제 실행 편의만을 위해 넣지 않습니다.