sqlite3 --- SQLite 데이터베이스용 DB-API 2.0 인터페이스

소스 코드: Lib/sqlite3/


SQLite는 별도의 서버 프로세스가 필요 없고 SQL 질의 언어의 비표준 변형을 사용하여 데이터베이스에 액세스할 수 있는 경량 디스크 기반 데이터베이스를 제공하는 C 라이브러리입니다. 일부 응용 프로그램은 내부 데이터 저장을 위해 SQLite를 사용할 수 있습니다. SQLite를 사용하여 응용 프로그램을 프로토타입 한 다음 PostgreSQL 이나 Oracle과 같은 더 큰 데이터베이스로 코드를 이식할 수도 있습니다.

sqlite3 모듈은 Gerhard Häring이 썼습니다. PEP 249에서 설명하는 DB-API 2.0 명세를 준수하는 SQL 인터페이스를 제공합니다.

모듈을 사용하려면, 먼저 데이터베이스를 나타내는 Connection 객체를 만들어야 합니다. 여기서 데이터는 example.db 파일에 저장됩니다

import sqlite3
conn = sqlite3.connect('example.db')

특수 이름 :memory:를 제공하여 램에 데이터베이스를 만들 수도 있습니다.

일단 Connection를 얻으면, Cursor 객체를 만들고 execute() 메서드를 호출하여 SQL 명령을 수행할 수 있습니다.:

c = conn.cursor()

# 테이블을 만듭니다
c.execute('''CREATE TABLE stocks
             (date text, trans text, symbol text, qty real, price real)''')

# 데이터 행을 삽입합니다
c.execute("INSERT INTO stocks VALUES ('2006-01-05','BUY','RHAT',100,35.14)")

# 변경을 저장(commit)합니다
conn.commit()

# 작업이 끝나면 연결을 닫을 수도 있습니다.
# 모든 변경 사항이 커밋되었음을 확인하십시오. 그렇지 않으면 잃어버립니다.
conn.close()

저장한 데이터는 영구적이며 이후 세션에서 사용할 수 있습니다:

import sqlite3
conn = sqlite3.connect('example.db')
c = conn.cursor()

일반적으로 SQL 연산은 파이썬 변수의 값을 사용해야 합니다. 파이썬의 문자열 연산을 사용하여 질의를 조합해서는 안 됩니다. 그렇게 하는 것은 안전하지 않기 때문입니다; 프로그램이 SQL 인젝션 공격에 취약하게 만듭니다 (잘못될 수 있는 유머러스한 예를 보려면 https://xkcd.com/327/ 를 참조하십시오).

대신 DB-API의 매개 변수 치환을 사용하십시오. 값을 사용하고자 할 때마다 ?를 자리 표시자로 넣은 다음, 커서의 execute() 메서드에 두 번째 인자로 값들의 튜플을 제공하십시오. (다른 데이터베이스 모듈은 다른 자리 표시자를 사용할 수 있습니다, 가령 %s:1.) 예를 들면:

# 절대로 하지 마십시오 -- 안전하지 않습니다!
symbol = 'RHAT'
c.execute("SELECT * FROM stocks WHERE symbol = '%s'" % symbol)

# 대신 이렇게 하세요
t = ('RHAT',)
c.execute('SELECT * FROM stocks WHERE symbol=?', t)
print(c.fetchone())

# 한 번에 많은 레코드를 삽입하는 더 큰 예
purchases = [('2006-03-28', 'BUY', 'IBM', 1000, 45.00),
             ('2006-04-05', 'BUY', 'MSFT', 1000, 72.00),
             ('2006-04-06', 'SELL', 'IBM', 500, 53.00),
            ]
c.executemany('INSERT INTO stocks VALUES (?,?,?,?,?)', purchases)

SELECT 문을 실행한 후 데이터를 꺼내려면, 커서를 이터레이터로 취급하거나, 커서의 fetchone() 메서드를 호출하여 일치하는 단일 행을 꺼내거나, fetchall()를 호출하여 일치하는 행의 리스트를 가져올 수 있습니다.

이 예제는 이터레이터 방식을 사용합니다:

>>> for row in c.execute('SELECT * FROM stocks ORDER BY price'):
        print(row)

('2006-01-05', 'BUY', 'RHAT', 100, 35.14)
('2006-03-28', 'BUY', 'IBM', 1000, 45.0)
('2006-04-06', 'SELL', 'IBM', 500, 53.0)
('2006-04-05', 'BUY', 'MSFT', 1000, 72.0)

더 보기

https://github.com/ghaering/pysqlite

pysqlite 웹 페이지 -- sqlite3은 "pysqlite"라는 이름으로 외부에서 개발되었습니다.

https://www.sqlite.org

SQLite 웹 페이지; 설명서는 지원되는 SQL 언어에 대한 문법과 사용 가능한 데이터형을 설명합니다.

https://www.w3schools.com/sql/

SQL 문법 학습을 위한 자습서, 레퍼런스 및 예제

PEP 249 - 데이터베이스 API 명세 2.0

Marc-André Lemburg가 작성한 PEP.

모듈 함수와 상수

flowdas

이 설명서에는 나와있지 않지만 DB-API 2.0은 세 개의 모듈 전역 상수를 정의하고 있습니다: apilevel, threadsafety, paramstyle. sqlite3 에는 세 상수 모두 정의되어 있습니다.

sqlite3.version

이 모듈의 버전 번호(문자열). SQLite 라이브러리의 버전이 아닙니다.

sqlite3.version_info

이 모듈의 버전 번호(정수들의 튜플). SQLite 라이브러리의 버전이 아닙니다.

sqlite3.sqlite_version

런타임 SQLite 라이브러리의 버전 번호(문자열).

sqlite3.sqlite_version_info

런타임 SQLite 라이브러리의 버전 번호(정수들의 튜플).

sqlite3.PARSE_DECLTYPES

이 상수는 connect() 함수의 detect_types 매개 변수에 사용됩니다.

이것을 설정하면 sqlite3 모듈은 반환되는 각 열에 대해 선언된 형을 구문 분석합니다. 선언된 형의 첫 번째 단어를 구문 분석합니다, 즉 "integer primary key"에서는 "integer"를, "number (10)"에서는 "number"를 구문 분석합니다. 그런 다음 해당 열에 대해, 변환기 딕셔너리를 조사하고 그 형에 대해 등록된 변환기 함수를 사용합니다.

sqlite3.PARSE_COLNAMES

이 상수는 connect() 함수의 detect_types 매개 변수에 사용됩니다.

이것을 설정하면 SQLite 인터페이스는 반환되는 각 열의 열 이름을 구문 분석합니다. 거기에서 [mytype] 형태의 문자열을 찾은 다음 'mytype'을 열의 형으로 결정합니다. 변환기 딕셔너리에서 'mytype' 항목을 찾은 다음 거기에 있는 변환기 함수를 사용하여 값을 반환하려고 시도합니다. Cursor.description에서 발견되는 열 이름은 열 이름의 첫 번째 단어일 뿐입니다. 즉, SQL에서 'as "x [datetime]"'와 같은 것을 사용하면, 열 이름의 첫 번째 공백까지 모든 것을 구문 분석합니다: 열 이름은 단순히 "x" 가 됩니다.

sqlite3.connect(database[, timeout, detect_types, isolation_level, check_same_thread, factory, cached_statements, uri])

flowdas

DB-API 2.0 이 정의하는 함수입니다. 이 함수가 반환하는 Connection 객체도 DB-API 2.0 이 정의합니다. 하지만 인자는 데이터베이스 종속적이고 DB-API 2.0은 어떤 매개 변수도 정의하지 않습니다. 다만 매개 변수를 정의하는 지침은 제공하고 있는데, 다음과 같은 키워드 매개 변수입니다.

  • dsn - 필수. 문자열 데이터 소스 이름.

  • user - 선택적. 사용자 이름.

  • password - 선택적. 암호.

  • host - 선택적. 호스트 이름.

  • database - 선택적. 데이터베이스 이름.

sqlite3 는 이 중 database 만 사용하고 있습니다만, 실제 의미는 이 지침의 dsn 에 해당합니다.

SQLite 데이터베이스 파일 database에 대한 연결을 엽니다. 사용자 정의 factory가 주어지지 않는 한, 기본적으로 Connection 객체를 반환합니다.

database는 열릴 데이터베이스 파일의 경로명(절대 혹은 현재 작업 디렉터리에 대한 상대)을 제공하는 경로류 객체입니다. ":memory:"를 사용하여 디스크 대신 램(RAM)에 있는 데이터베이스에 대한 데이터베이스 연결을 열 수 있습니다.

flowdas

database 에 빈 문자열을 주면 임시 파일이 사용되고, 연결이 닫히면 파일은 삭제됩니다. 데이터베이스가 파일에 만들어진다는 점을 제외하면 모든 면에서 ":memory:" 와 비슷합니다.

데이터베이스가 여러 연결을 통해 액세스 되고, 프로세스 중 하나가 데이터베이스를 수정할 때, 해당 트랜잭션이 커밋될 때까지 SQLite 데이터베이스가 잠깁니다. timeout 매개 변수는 예외를 일으키기 전에 잠금이 해제되기를 연결이 기다려야 하는 시간을 지정합니다. timeout 매개 변수의 기본값은 5.0(5초)입니다.

isolation_level 매개 변수는 Connection 객체의 isolation_level 프로퍼티를 참조하십시오.

SQLite는 기본적으로 TEXT, INTEGER, REAL, BLOB 및 NULL 형만 지원합니다. 다른 형을 사용하려면 직접 지원을 추가해야 합니다. detect_types 매개 변수와 모듈 수준 register_converter() 함수로 등록된 사용자 정의 변환기를 사용하면 쉽게 할 수 있습니다.

detect_types의 기본값은 0입니다 (즉, 형 감지가 없습니다). PARSE_DECLTYPESPARSE_COLNAMES의 조합으로 설정하여 형 감지를 켤 수 있습니다.

기본적으로 check_same_threadTrue며, 만들고 있는 스레드 만 이 연결을 사용할 수 있습니다. False로 설정하면 반환된 연결을 여러 스레드에서 공유할 수 있습니다. 여러 스레드에서 같은 연결을 사용할 때, 데이터 손상을 피하려면 쓰기 연산을 사용자가 직렬화해야 합니다.

기본적으로, sqlite3 모듈은 connect 호출에 Connection 클래스를 사용합니다. 그러나, Connection 클래스의 서브 클래스를 만들고 factory 매개 변수에 클래스를 제공하면 connect()가 그 클래스를 사용하게 할 수 있습니다.

자세한 내용은 이 설명서의 섹션 SQLite 와 파이썬 형을 참조하십시오.

sqlite3 모듈은 내부적으로 SQL 구문 분석 오버헤드를 피하고자 명령문 캐시를 사용합니다. 연결에 대해 캐시 되는 명령문의 수를 명시적으로 설정하려면, cached_statements 매개 변수를 설정할 수 있습니다. 현재 구현된 기본값은 100개의 명령문을 캐시 하는 것입니다.

uri가 참이면 database는 URI로 해석됩니다. 이렇게 하면 옵션을 지정할 수 있습니다. 예를 들어, 읽기 전용 모드로 데이터베이스를 열려면 다음과 같이 할 수 있습니다:

db = sqlite3.connect('file:path/to/database?mode=ro', uri=True)

인식되는 옵션 목록을 포함하여, 이 기능에 대한 자세한 내용은 SQLite URI documentation에서 찾을 수 있습니다.

인자 database감사 이벤트(auditing event) sqlite3.connect를 발생시킵니다.

버전 3.4에서 변경: uri 매개 변수가 추가되었습니다.

버전 3.7에서 변경: database는 이제 문자열뿐만 아니라 경로류 객체 일 수도 있습니다.

sqlite3.register_converter(typename, callable)

데이터베이스의 바이트열을 사용자 정의 파이썬 형으로 변환할 수 있는 콜러블을 등록합니다. 콜러블은 형 typename 인 모든 데이터베이스 값에 대해 호출됩니다. 형 감지 작동 방식에 대해서는 connect() 함수의 매개 변수 detect_types를 참고하십시오. typename과 질의의 형 이름은 대/소문자를 구분하지 않고 일치시킴에 유의하십시오.

sqlite3.register_adapter(type, callable)

사용자 정의 파이썬 형 type을 SQLite의 지원되는 형 중 하나로 변환할 수 있는 콜러블을 등록합니다. 콜러블 callable은 단일 매개 변수로 파이썬 값을 받아들이고 다음 형들의 값을 반환해야 합니다: int, float, str 또는 bytes.

sqlite3.complete_statement(sql)

문자열 sql에 세미콜론으로 끝나는 하나 이상의 완전한 SQL 문이 포함되어 있으면 True를 반환합니다. SQL이 문법적으로 올바른지 확인하지는 않습니다. 닫히지 않은 문자열 리터럴이 없고 명령문이 세미콜론으로 끝나는지만 확인합니다.

이것은 다음 예제와 같이, SQLite 용 셸을 만드는데 사용할 수 있습니다:

# 실험을 위한 최소 SQLite 셸

import sqlite3

con = sqlite3.connect(":memory:")
con.isolation_level = None
cur = con.cursor()

buffer = ""

print("Enter your SQL commands to execute in sqlite3.")
print("Enter a blank line to exit.")

while True:
    line = input()
    if line == "":
        break
    buffer += line
    if sqlite3.complete_statement(buffer):
        try:
            buffer = buffer.strip()
            cur.execute(buffer)

            if buffer.lstrip().upper().startswith("SELECT"):
                print(cur.fetchall())
        except sqlite3.Error as e:
            print("An error occurred:", e.args[0])
        buffer = ""

con.close()
sqlite3.enable_callback_tracebacks(flag)

기본적으로 사용자 정의 함수, 집계(aggregates), 변환기, 인가(authorizer) 콜백 등에서는 트레이스백을 얻지 못합니다. 디버깅하려면 flagTrue로 설정하여 이 함수를 호출할 수 있습니다. 그러면, sys.stderr로 콜백의 트레이스백을 얻게 됩니다. 기능을 다시 비활성화하려면 False를 사용하십시오.

Connection 객체

class sqlite3.Connection

flowdas

DB-API 2.0이 정의하는 클래스입니다.

SQLite 데이터베이스 연결에는 다음과 같은 어트리뷰트와 메서드가 있습니다:

isolation_level

현재의 기본 격리 수준을 가져오거나 설정합니다. 자동 커밋 모드를 뜻하는 None 이나 "DEFERRED", "IMMEDIATE" 또는 "EXCLUSIVE" 중 하나입니다. 자세한 설명은 트랜잭션 제어 절을 참조하십시오.

flowdas

isolation_level 의 기본값은 "" 입니다. 이 값은 None 과는 다른 것이며 "DEFERRED" 와 같은 방식으로 동작합니다.

in_transaction

트랜잭션이 활성화 상태면(커밋되지 않은 변경 사항이 있으면) True, 그렇지 않으면 False. 읽기 전용 어트리뷰트.

버전 3.2에 추가.

cursor(factory=Cursor)

flowdas

DB-API 2.0이 정의하는 메서드입니다. 다만 factory 매개 변수는 정의하지 않습니다.

cursor 메서드는 단일 선택적 매개 변수 factory를 받아들입니다. 제공되면, 이것은 Cursor 나 그 서브 클래스의 인스턴스를 반환하는 콜러블이어야 합니다.

commit()

flowdas

DB-API 2.0이 정의하는 메서드입니다.

이 메서드는 현재 트랜잭션을 커밋합니다. 이 메서드를 호출하지 않으면, 마지막 commit() 호출 이후에 수행한 작업은 다른 데이터베이스 연결에서 볼 수 없습니다. 데이터베이스에 기록한 데이터가 왜 보이지 않는지 궁금하면, 이 메서드를 호출하는 것을 잊지 않았는지 확인하십시오.

rollback()

flowdas

DB-API 2.0이 정의하는 메서드입니다.

이 메서드는 마지막 commit() 호출 이후의 데이터베이스에 대한 모든 변경 사항을 되돌립니다.

close()

flowdas

DB-API 2.0이 정의하는 메서드입니다.

데이터베이스 연결을 닫습니다. 자동으로 commit()을 호출하지 않음에 유의하십시오. commit()를 먼저 호출하지 않고 데이터베이스 연결을 닫으면 변경 사항이 손실됩니다!

execute(sql[, parameters])

이것은 비표준 바로 가기인데, cursor() 메서드를 호출하여 커서 객체를 만들고, 지정된 parameters를 사용하여 커서의 execute() 메서드를 호출한 다음, 커서를 반환합니다.

executemany(sql[, parameters])

이것은 비표준 바로 가기인데, cursor() 메서드를 호출하여 커서 객체를 만들고, 지정된 parameters를 사용하여 커서의 executemany() 메서드를 호출한 다음, 커서를 반환합니다.

executescript(sql_script)

이것은 비표준 바로 가기인데, cursor() 메서드를 호출하여 커서 객체를 만들고, 지정된 sql_script를 사용하여 커서의 executescript() 메서드를 호출한 다음, 커서를 반환합니다.

create_function(name, num_params, func, *, deterministic=False)

나중에 함수 이름 name으로 SQL 문에서 사용할 수 있는 사용자 정의 함수를 만듭니다. num_params는 함수가 받아들이는 매개 변수의 수입니다 (num_params가 -1이면 함수는 임의의 인자를 취할 수 있습니다). func는 SQL 함수로 호출되는 파이썬 콜러블입니다. deterministic이 참이면, 만들어진 함수는 SQLite가 추가적인 최적화를 수행할 수 있도록 결정론적(deterministic)으로 표시됩니다. 이 플래그는 SQLite 3.8.3 이상에서 지원됩니다, 이전 버전에서 사용되면 NotSupportedError가 발생합니다.

함수는 SQLite가 지원하는 모든 형을 반환할 수 있습니다: bytes, str, int, float 및 None.

버전 3.8에서 변경: deterministic 매개 변수가 추가되었습니다.

예:

import sqlite3
import hashlib

def md5sum(t):
    return hashlib.md5(t).hexdigest()

con = sqlite3.connect(":memory:")
con.create_function("md5", 1, md5sum)
cur = con.cursor()
cur.execute("select md5(?)", (b"foo",))
print(cur.fetchone()[0])

con.close()
create_aggregate(name, num_params, aggregate_class)

사용자 정의 집계(aggregate) 함수를 만듭니다.

매개 변수의 수 num_params(num_params가 -1이면 함수는 임의의 인자를 취할 수 있습니다)를 받아들이며, 집계 클래스는 step 메서드와 집계의 최종 결과를 반환하는 finalize 메서드를 구현해야 합니다.

finalize 메서드는 SQLite가 지원하는 모든 형을 반환할 수 있습니다: bytes, str, int, float 및 None.

예:

import sqlite3

class MySum:
    def __init__(self):
        self.count = 0

    def step(self, value):
        self.count += value

    def finalize(self):
        return self.count

con = sqlite3.connect(":memory:")
con.create_aggregate("mysum", 1, MySum)
cur = con.cursor()
cur.execute("create table test(i)")
cur.execute("insert into test(i) values (1)")
cur.execute("insert into test(i) values (2)")
cur.execute("select mysum(i) from test")
print(cur.fetchone()[0])

con.close()
create_collation(name, callable)

지정된 namecallable로 정렬법(collation)을 만듭니다. 콜러블에는 두 개의 문자열 인자가 전달됩니다. 첫째가 둘째보다 작은 순서면 -1, 같은 순서면 0, 첫째가 둘째보다 큰 순서면 1을 반환 해야 합니다. 이것은 정렬(SQL의 ORDER BY)을 제어하므로, 여러분의 비교는 다른 SQL 연산에 영향을 주지 않습니다.

콜러블 객체는 보통 UTF-8로 인코딩된 파이썬 바이트열로 매개 변수를 가져옵니다.

다음 예제는 "잘못된 방법"으로 정렬하는 사용자 정의 정렬법을 보여줍니다:

import sqlite3

def collate_reverse(string1, string2):
    if string1 == string2:
        return 0
    elif string1 < string2:
        return 1
    else:
        return -1

con = sqlite3.connect(":memory:")
con.create_collation("reverse", collate_reverse)

cur = con.cursor()
cur.execute("create table test(x)")
cur.executemany("insert into test(x) values (?)", [("a",), ("b",)])
cur.execute("select x from test order by x collate reverse")
for row in cur:
    print(row)
con.close()

정렬법을 제거하려면 callable에 None을 사용해서 create_collation를 호출하십시오:

con.create_collation("reverse", None)
interrupt()

연결에서 실행 중일 수 있는 모든 질의를 중단하려면, 이 메서드를 다른 스레드에서 호출할 수 있습니다. 그러면 질의가 중단되고 호출자는 예외를 받습니다.

set_authorizer(authorizer_callback)

이 루틴은 콜백을 등록합니다. 콜백은 데이터베이스의 테이블 열에 액세스할 때마다 호출됩니다. 콜백은 액세스가 허용되면 SQLITE_OK를 반환하고, 전체 SQL 문을 에러를 일으키며 중단해야 하면 SQLITE_DENY를, 열을 NULL 값으로 처리하려면 SQLITE_IGNORE를 반환해야 합니다. 이 상수들은 sqlite3 모듈에 있습니다.

콜백의 첫 번째 인자는 어떤 종류의 연산이 인가받으려 하는지를 나타냅니다. 두 번째와 세 번째 인자는 첫 번째 인자에 따라 인자이거나 None이 됩니다. 네 번째 인자는 해당하면 데이터베이스 이름("main", "temp" 등)입니다. 다섯 번째 인자는 액세스 시도를 담당하는 가장 안쪽의 트리거나 뷰의 이름이거나, 이 액세스 시도가 입력 SQL 코드에서 직접 발생했으면 None입니다.

첫 번째 인자에 가능한 값과 첫 번째 인자에 의존하는 두 번째 및 세 번째 인자의 의미에 대해서는 SQLite 문서를 참조하십시오. 필요한 모든 상수는 sqlite3 모듈에 있습니다.

set_progress_handler(handler, n)

이 루틴은 콜백을 등록합니다. 콜백은 SQLite 가상 머신의 매 n개의 명령어마다 호출됩니다. 장시간 실행되는 작업 중에 SQLite로부터 호출되기를 원할 때 유용합니다, 예를 들어 GUI를 갱신하는데 사용할 수 있습니다.

이전에 설치된 모든 진행 처리기를 지우려면 handlerNone을 사용하여 메서드를 호출하십시오.

처리기 함수에서 0이 아닌 값을 반환하면 현재 실행 중인 질의가 종료되고 OperationalError 예외가 발생합니다.

set_trace_callback(trace_callback)

SQLite 백 엔드가 실제로 실행하는 각 SQL 문마다 호출할 trace_callback을 등록합니다.

콜백에 전달되는 유일한 인자는 실행 중인 문장(문자열)입니다. 콜백의 반환 값은 무시됩니다. 백 엔드는 Cursor.execute() 메서드에 전달된 명령문만 실행하는 것은 아님에 유의하시기 바랍니다. 다른 소스로는 파이썬 모듈의 트랜잭션 관리와 현재 데이터베이스에 정의된 트리거의 실행이 있습니다.

Nonetrace_callback로 전달하면 추적 콜백을 비활성화합니다.

버전 3.3에 추가.

enable_load_extension(enabled)

이 루틴은 SQLite 엔진이 공유 라이브러리에서 SQLite 확장을 로드하는 것을 허용/불허합니다. SQLite 확장은 새 함수, 집계 또는 완전히 새로운 가상 테이블 구현을 정의할 수 있습니다. 잘 알려진 확장 중 하나는 SQLite와 함께 배포되는 전체 텍스트 검색 확장입니다.

로드 가능한 확장은 기본적으로 비활성화되어 있습니다. 1를 보세요.

버전 3.2에 추가.

import sqlite3

con = sqlite3.connect(":memory:")

# 확장 로드를 활성화합니다
con.enable_load_extension(True)

# 전체 텍스트 검색 확장을 로드합니다
con.execute("select load_extension('./fts3.so')")

# 대신 API 호출을 사용하여 확장을 로드할 수도 있습니다:
# con.load_extension("./fts3.so")

# 확장 로드를 다시 비활성화합니다
con.enable_load_extension(False)

# SQLite 위키의 예제
con.execute("create virtual table recipe using fts3(name, ingredients)")
con.executescript("""
    insert into recipe (name, ingredients) values ('broccoli stew', 'broccoli peppers cheese tomatoes');
    insert into recipe (name, ingredients) values ('pumpkin stew', 'pumpkin onions garlic celery');
    insert into recipe (name, ingredients) values ('broccoli pie', 'broccoli cheese onions flour');
    insert into recipe (name, ingredients) values ('pumpkin pie', 'pumpkin sugar flour butter');
    """)
for row in con.execute("select rowid, name, ingredients from recipe where name match 'pie'"):
    print(row)

con.close()
load_extension(path)

이 루틴은 공유 라이브러리에서 SQLite 확장을 로드합니다. 이 루틴을 사용하려면 먼저 enable_load_extension()로 확장 로드를 활성화해야 합니다.

로드 가능한 확장은 기본적으로 비활성화되어 있습니다. 1를 보세요.

버전 3.2에 추가.

row_factory

이 어트리뷰트를 커서와 원본 행을 튜플로 받아들이고 실제 결과 행을 반환하는 콜러블로 변경할 수 있습니다. 이렇게 하면, 이름으로 열을 액세스할 수 있는 객체를 반환하는 것과 같이, 결과를 반환하는 더 고급 방식을 구현할 수 있습니다.

예:

import sqlite3

def dict_factory(cursor, row):
    d = {}
    for idx, col in enumerate(cursor.description):
        d[col[0]] = row[idx]
    return d

con = sqlite3.connect(":memory:")
con.row_factory = dict_factory
cur = con.cursor()
cur.execute("select 1 as a")
print(cur.fetchone()["a"])

con.close()

튜플을 반환하는 것으로 충분하지 않고 열에 대한 이름 기반 액세스를 원하면, row_factory를 고도로 최적화된 sqlite3.Row 형으로 설정하는 것을 고려해야 합니다. Row는 메모리 오버헤드가 거의 없이 열에 대해 인덱스 기반과 대소 문자를 구분하지 않는 이름 기반 액세스를 제공합니다. 아마도 여러분 자신의 사용자 정의 딕셔너리 기반 접근법이나 심지어 db_row 기반 해법보다 더 좋을 것입니다.

text_factory

이 어트리뷰트를 사용하면 TEXT 데이터형에 대해 반환되는 객체를 제어할 수 있습니다. 기본적으로, 이 어트리뷰트는 str로 설정되고 sqlite3 모듈은 TEXT에 대해 유니코드 객체를 반환합니다. 대신 바이트열을 반환하려면, bytes로 설정할 수 있습니다.

하나의 바이트열 매개 변수를 받아들이고 결과 객체를 반환하는 다른 콜러블 객체로 설정할 수도 있습니다.

예시를 위해 다음 예제 코드를 참조하십시오:

import sqlite3

con = sqlite3.connect(":memory:")
cur = con.cursor()

AUSTRIA = "\xd6sterreich"

# 기본적으로, 행은 유니코드로 반환됩니다
cur.execute("select ?", (AUSTRIA,))
row = cur.fetchone()
assert row[0] == AUSTRIA

# 하지만 우리는 sqlite3가 항상 바이트열을 반환하도록 할 수 있습니다 ...
con.text_factory = bytes
cur.execute("select ?", (AUSTRIA,))
row = cur.fetchone()
assert type(row[0]) is bytes
# 여러분이 데이터베이스에 쓰레기를 저장하지 않는 이상, 바이트열은 UTF-8로 인코딩될 것입니다 ...
assert row[0] == AUSTRIA.encode("utf-8")

# 우리는 또한 사용자 정의 text_factory를 구현할 수 있습니다 ...
# 여기서 모든 문자열에 "foo"를 추가하는 것을 구현합니다
con.text_factory = lambda x: x.decode("utf-8") + "foo"
cur.execute("select ?", ("bar",))
row = cur.fetchone()
assert row[0] == "barfoo"

con.close()
total_changes

데이터베이스 연결이 열린 후 수정, 삽입 또는 삭제된 데이터베이스 행의 총수를 반환합니다.

iterdump()

SQL 텍스트 형식으로 데이터베이스를 덤프하는 이터레이터를 반환합니다. 나중에 복원할 수 있도록 메모리 데이터베이스를 저장할 때 유용합니다. 이 함수는 sqlite3 셸의 .dump 명령과 같은 기능을 제공합니다.

예:

# existing_db.db 파일을 SQL 덤프 파일 dump.sql로 변환합니다
import sqlite3

con = sqlite3.connect('existing_db.db')
with open('dump.sql', 'w') as f:
    for line in con.iterdump():
        f.write('%s\n' % line)
con.close()
backup(target, *, pages=0, progress=None, name="main", sleep=0.250)

이 메서드는 SQLite 데이터베이스의 백업을 만드는데, 다른 클라이언트가 액세스하고 있거나 같은 연결로 동시에 액세스하고 있어도 됩니다. 복사본은 필수 인자 target에 기록되며, 이것은 다른 Connection 인스턴스여야 합니다.

기본적으로, 또는 pages0 이나 음의 정수이면, 전체 데이터베이스가 단일 단계로 복사됩니다; 그렇지 않으면 이 메서드는 한 번에 최대 pages 페이지만큼 복사하는 루프를 수행합니다.

progress가 지정되면, None 또는 매 이터레이션마다 세 개의 정수 인자로 실행되는 콜러블 객체여야 합니다. 세 인자는 각각 직전 이터레이션의 상태(status), 아직 복사해야 할 남은(remaining) 페이지 수, 전체(total) 페이지 수입니다.

name 인자는 복사할 데이터베이스 이름을 지정합니다: main 데이터베이스를 나타내는 "main", 기본값, 임시 데이터베이스를 나타내는 "temp" 또는 첨부된 데이터베이스를 위한 ATTACH DATABASE 문에서 AS 키워드 뒤에 지정된 이름을 포함하는 문자열이어야 합니다.

sleep 인자는 남은 페이지를 백업하는 연속적인 시도 사이에서 잠잘 시간을 초 단위로 지정하며, 정수 또는 부동 소수점 값으로 지정할 수 있습니다.

예제 1, 기존 데이터베이스를 다른 데이터베이스로 복사:

import sqlite3

def progress(status, remaining, total):
    print(f'Copied {total-remaining} of {total} pages...')

con = sqlite3.connect('existing_db.db')
bck = sqlite3.connect('backup.db')
with bck:
    con.backup(bck, pages=1, progress=progress)
bck.close()
con.close()

예제 2, 기존 데이터베이스를 임시 복사본으로 복사:

import sqlite3

source = sqlite3.connect('existing_db.db')
dest = sqlite3.connect(':memory:')
source.backup(dest)

가용성: SQLite 3.6.11 이상

버전 3.7에 추가.

Cursor 객체

class sqlite3.Cursor

flowdas

DB-API 2.0이 정의하는 클래스입니다. 이 설명서에는 나와있지 않지만 DB-API 2.0이 필수로 정의하는 setinputsizes()setoutputsize() 메서드도 정의되어 있습니다. 두 메서드 모두 아무일도 하지 않습니다.

Cursor 인스턴스에는 다음과 같은 어트리뷰트와 메서드가 있습니다.

execute(sql[, parameters])

flowdas

DB-API 2.0이 정의하는 메서드입니다.

SQL 문을 실행합니다. SQL 문을 매개 변수화(즉, SQL 리터럴 대신 자리 표시자)할 수 있습니다. sqlite3 모듈은 두 가지 자리 표시자를 지원합니다: 물음표(qmark 스타일)와 이름있는 자리 표시자(named 스타일).

flowdas

DB-API 2.0은 다섯 종류의 자리표시자를 정의하고 있습니다: qmark, numeric, named, format, pyformat. 이 중 어느 것을 지원하는지는 모듈 전역으로 정의되는 paramstyle 문자열 상수로 알려주도록 하고 있습니다. sqlite3qmarknamed 를 지원하지만, sqlite3.paramstyleqmark 라고 알려주고 있습니다. 하지만 DB-API 2.0 은 가능하다면 numeric, named, pyformat 중 하나를 사용하도록 권고하고 있습니다.

다음은 두 스타일의 예입니다:

import sqlite3

con = sqlite3.connect(":memory:")
cur = con.cursor()
cur.execute("create table people (name_last, age)")

who = "Yeltsin"
age = 72

# qmark 스타일입니다:
cur.execute("insert into people values (?, ?)", (who, age))

# named 스타일입니다:
cur.execute("select * from people where name_last=:who and age=:age", {"who": who, "age": age})

print(cur.fetchone())

con.close()

execute()는 단일 SQL 문만 실행합니다. 하나 이상의 명령문을 실행하려고 하면 Warning이 발생합니다. 하나의 호출로 여러 SQL 문을 실행하려면 executescript()를 사용하십시오.

executemany(sql, seq_of_parameters)

flowdas

DB-API 2.0이 정의하는 메서드입니다.

시퀀스 seq_of_parameters에 있는 모든 매개 변수 시퀀스나 매핑에 대해 SQL 명령을 실행합니다. sqlite3 모듈은 시퀀스 대신 매개 변수를 산출하는 이터레이터도 허용합니다.

import sqlite3

class IterChars:
    def __init__(self):
        self.count = ord('a')

    def __iter__(self):
        return self

    def __next__(self):
        if self.count > ord('z'):
            raise StopIteration
        self.count += 1
        return (chr(self.count - 1),) # this is a 1-tuple

con = sqlite3.connect(":memory:")
cur = con.cursor()
cur.execute("create table characters(c)")

theIter = IterChars()
cur.executemany("insert into characters(c) values (?)", theIter)

cur.execute("select c from characters")
print(cur.fetchall())

con.close()

다음은 제너레이터를 사용하는 간단한 예입니다:

import sqlite3
import string

def char_generator():
    for c in string.ascii_lowercase:
        yield (c,)

con = sqlite3.connect(":memory:")
cur = con.cursor()
cur.execute("create table characters(c)")

cur.executemany("insert into characters(c) values (?)", char_generator())

cur.execute("select c from characters")
print(cur.fetchall())

con.close()
executescript(sql_script)

이것은 한 번에 여러 SQL 문을 실행하기 위한 비표준 편의 메서드입니다. 먼저 COMMIT 문을 실행한 다음, 매개 변수로 가져온 SQL 스크립트를 실행합니다.

sql_scriptstr의 인스턴스가 될 수 있습니다.

예:

import sqlite3

con = sqlite3.connect(":memory:")
cur = con.cursor()
cur.executescript("""
    create table person(
        firstname,
        lastname,
        age
    );

    create table book(
        title,
        author,
        published
    );

    insert into book(title, author, published)
    values (
        'Dirk Gently''s Holistic Detective Agency',
        'Douglas Adams',
        1987
    );
    """)
con.close()
fetchone()

flowdas

DB-API 2.0이 정의하는 메서드입니다.

질의 결과 집합의 다음 행을 가져옵니다. 단일 시퀀스를 반환하거나, 데이터가 더 없을 때 None을 반환합니다.

fetchmany(size=cursor.arraysize)

flowdas

DB-API 2.0이 정의하는 메서드입니다.

질의 결과의 다음 행 집합을 가져와서, 리스트를 반환합니다. 행이 더 없으면 빈 목록이 반환됩니다.

호출 당 가져오는 행의 수는 size 매개 변수로 지정됩니다. 지정되어 않으면, 커서의 arraysize가 가져올 행의 수를 결정합니다. 이 메서드는 size 매개 변수가 나타내는 수만큼의 행을 가져오려고 해야 합니다. 지정된 수의 행이 없어서 이것이 가능하지 않다면, 더 적은 행이 반환될 수 있습니다.

size 매개 변수와 관련된 성능 고려 사항이 있습니다. 최적의 성능을 위해서, 일반적으로 arraysize 어트리뷰트를 사용하는 것이 가장 좋습니다. size 매개 변수가 사용되면, fetchmany() 호출마다 같은 값을 유지하는 것이 가장 좋습니다.

fetchall()

flowdas

DB-API 2.0이 정의하는 메서드입니다.

질의 결과의 모든 (남은) 행을 가져와서 리스트를 반환합니다. 커서의 arraysize 어트리뷰트는 이 연산의 성능에 영향을 줄 수 있습니다. 행이 없으면 빈 리스트가 반환됩니다.

close()

flowdas

DB-API 2.0이 정의하는 메서드입니다.

(__del__이 호출 될 때가 아니라) 지금 커서를 닫습니다.

이 시점부터는 커서를 사용할 수 없습니다; 커서로 어떤 연산이건 시도하면 ProgrammingError 예외가 발생합니다.

rowcount

flowdas

DB-API 2.0이 정의하는 어트리뷰트입니다.

sqlite3 모듈의 Cursor 클래스가 이 어트리뷰트를 구현하지만, "영향을 받는 행"/"선택된 행"의 판단을 위한 데이터베이스 엔진 자체 지원은 기이합니다.

executemany() 문에서, 수정 횟수는 rowcount에 합산됩니다.

파이썬 DB API 스펙에 따라, rowcount 어트리뷰트는 커서에서 executeXX()가 수행되지 않았거나 마지막 연산의 행 개수가 인터페이스에 의해 결정되지 않는 경우 -1입니다. 이런 경우는 SELECT 문을 포함하는데, 모든 행을 가져올 때까지 질의가 생성 한 행 수를 결정할 수 없기 때문입니다.

3.6.5 이전의 SQLite 버전에서는, 조건 없이 DELETE FROM table을 하면 rowcount가 0으로 설정됩니다.

lastrowid

flowdas

DB-API 2.0이 선택적으로 정의하는 어트리뷰트입니다.

이 읽기 전용 어트리뷰트는 마지막으로 수정된 행의 rowid를 제공합니다. execute() 메서드를 사용하여 INSERTREPLACE 문을 실행했을 때만 설정됩니다. INSERTREPLACE 이외의 연산이나 executemany()가 호출될 때, lastrowidNone으로 설정됩니다.

INSERTREPLACE 문이 삽입에 실패하면, 이전의 성공적인 rowid가 반환됩니다.

버전 3.6에서 변경: REPLACE 문에 대한 지원이 추가되었습니다.

arraysize

flowdas

DB-API 2.0이 정의하는 어트리뷰트입니다.

fetchmany()에 의해 반환되는 행의 수를 제어하는 읽기/쓰기 어트리뷰트. 기본값은 1입니다. 이는 호출 당 하나의 행을 가져오는 것을 뜻합니다.

description

flowdas

DB-API 2.0이 정의하는 어트리뷰트입니다. 하지만 그 내용은 규격에서 살짝 벗어납니다. DB-API 2.0은 처음 두 항목 nametype_code를 필수 항목으로 정의하고 있습니다. 하지만 sqlite3description 의 두 번째 항목으로 항상 None을 줍니다. DB-API 2.0은 type_code\를 통해 열의 형을 파악할 수 있도록 하고 있고, 이 값과 비교할 수 있는 다음과 같은 형들을 모듈 수준에서 정의하고 있습니다: STRING, BINARY, NUMBER, DATETIME, ROWID. sqlite3 모듈은 이 형들도 정의하고 있지 않습니다.

이 읽기 전용 어트리뷰트는 마지막 질의의 열 이름을 제공합니다. 파이썬 DB API와의 호환성을 유지하기 위해, 각 열마다 7-튜플을 반환하는데, 각 튜플의 마지막 6개 항목은 None 입니다.

일치하는 행이 없는 SELECT 문에도 설정됩니다.

connection

flowdas

DB-API 2.0이 선택적으로 정의하는 어트리뷰트입니다.

이 읽기 전용 어트리뷰트는 Cursor 객체가 사용하는 SQLite 데이터베이스 Connection을 제공합니다. con.cursor()를 호출하여 생성된 Cursor 객체는 con을 참조하는 connection 어트리뷰트를 가집니다:

>>> con = sqlite3.connect(":memory:")
>>> cur = con.cursor()
>>> cur.connection == con
True

Row 객체

class sqlite3.Row

Row 인스턴스는 Connection 객체에 대해 고도로 최적화된 row_factory 역할을 합니다. 대부분 기능에서 튜플을 모방하려고 합니다.

열 이름과 인덱스에 의한 매핑 액세스와, 이터레이션, 표현(repr), 동등성 검사 및 len()을 지원합니다.

두 개의 Row 객체가 정확히 같은 열을 갖고 그 구성원이 같으면 같다고 비교됩니다.

keys()

이 메서드는 열 이름 리스트를 반환합니다. 질의 직후, Cursor.description에 있는 각 튜플의 첫 번째 멤버입니다.

버전 3.5에서 변경: 슬라이싱 지원이 추가되었습니다.

위에서 주어진 예제에서처럼 테이블을 초기화한다고 가정해 봅시다:

conn = sqlite3.connect(":memory:")
c = conn.cursor()
c.execute('''create table stocks
(date text, trans text, symbol text,
 qty real, price real)''')
c.execute("""insert into stocks
          values ('2006-01-05','BUY','RHAT',100,35.14)""")
conn.commit()
c.close()

이제 우리는 Row를 연결합니다:

>>> conn.row_factory = sqlite3.Row
>>> c = conn.cursor()
>>> c.execute('select * from stocks')
<sqlite3.Cursor object at 0x7f4e7dd8fa80>
>>> r = c.fetchone()
>>> type(r)
<class 'sqlite3.Row'>
>>> tuple(r)
('2006-01-05', 'BUY', 'RHAT', 100.0, 35.14)
>>> len(r)
5
>>> r[2]
'RHAT'
>>> r.keys()
['date', 'trans', 'symbol', 'qty', 'price']
>>> r['qty']
100.0
>>> for member in r:
...     print(member)
...
2006-01-05
BUY
RHAT
100.0
35.14

예외

exception sqlite3.Warning

flowdas

DB-API 2.0이 정의하는 예외입니다.

Exception의 서브 클래스.

exception sqlite3.Error

flowdas

DB-API 2.0이 정의하는 예외입니다.

이 모듈에 있는 다른 예외의 베이스 클래스. Exception의 서브 클래스입니다.

exception sqlite3.DatabaseError

flowdas

DB-API 2.0이 정의하는 예외입니다.

데이터베이스와 관련된 에러에 대해 발생하는 예외.

exception sqlite3.IntegrityError

flowdas

DB-API 2.0이 정의하는 예외입니다.

데이터베이스의 관계형 무결성이 영향을 받을 때 발생하는 예외. 예를 들어, 외부 키(foreign key) 검사가 실패할 때. DatabaseError의 서브 클래스입니다.

exception sqlite3.ProgrammingError

flowdas

DB-API 2.0이 정의하는 예외입니다.

프로그래밍 에러에 대한 예외, 예를 들어, 테이블을 찾을 수 없거나 이미 존재 함, SQL 문의 문법 에러, 지정된 매개 변수 개수가 잘못됨 등. DatabaseError의 서브 클래스입니다.

exception sqlite3.OperationalError

flowdas

DB-API 2.0이 정의하는 예외입니다.

데이터베이스 연산과 관련되고 프로그래머의 제어하에 있지 않은 에러에 관한 오류. 예를 들어, 예기치 않은 단절이 발생하거나, 데이터 소스 이름을 찾을 수 없거나, 트랜잭션이 진행될 수 없을 때 등. DatabaseError의 서브 클래스입니다.

exception sqlite3.NotSupportedError

flowdas

DB-API 2.0이 정의하는 예외입니다.

데이터베이스에서 지원하지 않는 메서드나 데이터베이스 API가 사용될 때 발생하는 예외. 예를 들어, 트랜잭션을 지원하지 않는 연결에서 rollback() 메서드를 호출할 때. DatabaseError의 서브 클래스입니다.

SQLite 와 파이썬 형

소개

SQLite는 기본적으로 다음 형을 지원합니다: NULL, INTEGER, REAL, TEXT, BLOB.

따라서 다음과 같은 파이썬 형을 아무 문제 없이 SQLite로 보낼 수 있습니다:

파이썬 형

SQLite 형

None

NULL

int

INTEGER

float

REAL

str

TEXT

bytes

BLOB

이것은 SQLite 형이 기본적으로 파이썬 형으로 변환되는 방법입니다:

SQLite 형

파이썬 형

NULL

None

INTEGER

int

REAL

float

TEXT

text_factory에 따라 다릅니다, 기본적으로 str.

BLOB

bytes

sqlite3 모듈의 형 시스템은 두 가지 방식으로 확장 가능합니다: 객체 어댑터를 통해 SQLite 데이터베이스에 추가 파이썬 형을 저장할 수 있으며 변환기를 통해 sqlite3 모듈에서 SQLite 형을 다른 파이썬 형으로 변환할 수 있습니다.

flowdas

DB-API 2.0은 날짜, 시간, 바이너리를 데이터베이스로 전달하는 데 사용할 수 있는 모듈 수준 함수들을 몇가지 정의하고 있습니다. 이 모두를 sqlite3 가 지원하고 있지만 이 설명서에는 나오지 않습니다. 다음과 같은 함수입니다.

sqlite3.Date(year, month, day)
sqlite3.Time(hour, minute, second)
sqlite3.Timestamp(year, month, day, hour, minute, second)
sqlite3.DateFromTicks(ticks)
sqlite3.TimeFromTicks(ticks)
sqlite3.TimestampFromTicks(ticks)
sqlite3.Binary(string)

어댑터를 사용하여 SQLite 데이터베이스에 추가 파이썬 형을 저장하기

앞에서 설명한 것처럼, SQLite는 기본적으로 제한된 형 집합만 지원합니다. SQLite에 다른 파이썬 형을 사용하려면, SQLite에 대해 sqlite3 모듈이 지원하는 형 중 하나로 어댑트 해야 합니다: NoneType, int, float, str, bytes 중 하나.

sqlite3 모듈이 사용자 정의 파이썬 형을, 지원되는 형 중 하나로 어댑트하도록 만드는 두 가지 방법이 있습니다.

객체가 스스로 어댑트하도록 하기

여러분이 스스로 클래스를 작성한다면 이것이 좋은 접근법입니다. 다음과 같은 클래스가 있다고 가정해 봅시다:

class Point:
    def __init__(self, x, y):
        self.x, self.y = x, y

이제 Point를 단일 SQLite 열에 저장하려고 합니다. 먼저 포인트를 나타내는데 사용할 지원되는 형 중 하나를 선택해야 합니다. str을 사용하고 좌표를 세미콜론으로 분리하기로 합시다. 그런 다음 여러분의 클래스에 변환된 값을 반환하는 __conform__(self, protocol) 메서드를 제공해야 합니다. 매개 변수 protocolPrepareProtocol이 됩니다.

import sqlite3

class Point:
    def __init__(self, x, y):
        self.x, self.y = x, y

    def __conform__(self, protocol):
        if protocol is sqlite3.PrepareProtocol:
            return "%f;%f" % (self.x, self.y)

con = sqlite3.connect(":memory:")
cur = con.cursor()

p = Point(4.0, -3.2)
cur.execute("select ?", (p,))
print(cur.fetchone()[0])

con.close()

어댑터 콜러블 등록하기

또 다른 가능성은 형을 문자열 표현으로 변환하는 함수를 만들고. 그 함수를 register_adapter()로 등록하는 것입니다.

import sqlite3

class Point:
    def __init__(self, x, y):
        self.x, self.y = x, y

def adapt_point(point):
    return "%f;%f" % (point.x, point.y)

sqlite3.register_adapter(Point, adapt_point)

con = sqlite3.connect(":memory:")
cur = con.cursor()

p = Point(4.0, -3.2)
cur.execute("select ?", (p,))
print(cur.fetchone()[0])

con.close()

sqlite3 모듈에는 파이썬의 내장 datetime.datedatetime.datetime 형에 대한 두 개의 기본 어댑터가 있습니다. 이제 datetime.datetime 객체를 ISO 표현이 아닌 유닉스 타임스탬프로 저장하려고 한다고 가정해 봅시다.

import sqlite3
import datetime
import time

def adapt_datetime(ts):
    return time.mktime(ts.timetuple())

sqlite3.register_adapter(datetime.datetime, adapt_datetime)

con = sqlite3.connect(":memory:")
cur = con.cursor()

now = datetime.datetime.now()
cur.execute("select ?", (now,))
print(cur.fetchone()[0])

con.close()

SQLite 값을 사용자 정의 파이썬 형으로 변환하기

어댑터를 작성하면 사용자 정의 파이썬 형을 SQLite로 보낼 수 있습니다. 그러나 실제로 유용하게 사용하려면 파이썬에서 SQLite를 거쳐 다시 파이썬으로 돌아오는 순환이 동작하게 할 필요가 있습니다.

변환기를 사용하십시오.

Point 클래스로 돌아갑시다. 세미콜론으로 분리된 x와 y 좌표를 SQLite에 문자열로 저장했습니다.

먼저, 문자열을 매개 변수로 받아들이고 이것으로부터 Point 객체를 만드는 변환기 함수를 정의합니다.

참고

변환기 함수는 항상 SQLite로 보낸 값의 데이터형에 상관없이 bytes 객체로 호출됩니다.

def convert_point(s):
    x, y = map(float, s.split(b";"))
    return Point(x, y)

이제 sqlite3 모듈이 데이터베이스에서 select 한 것이 실제로 Point임을 알게 해야 합니다. 이렇게 하는 두 가지 방법이 있습니다:

  • 선언된 형을 통해 묵시적으로

  • 열 이름을 통해 명시적으로

두 가지 방법은 섹션 모듈 함수와 상수 의 상수 PARSE_DECLTYPESPARSE_COLNAMES에 대한 항목에서 설명합니다.

다음 예는 두 가지 접근법을 보여줍니다.

import sqlite3

class Point:
    def __init__(self, x, y):
        self.x, self.y = x, y

    def __repr__(self):
        return "(%f;%f)" % (self.x, self.y)

def adapt_point(point):
    return ("%f;%f" % (point.x, point.y)).encode('ascii')

def convert_point(s):
    x, y = list(map(float, s.split(b";")))
    return Point(x, y)

# 어댑터를 등록합니다
sqlite3.register_adapter(Point, adapt_point)

# 변환기를 등록합니다
sqlite3.register_converter("point", convert_point)

p = Point(4.0, -3.2)

#########################
# 1) 선언된 형 사용하기
con = sqlite3.connect(":memory:", detect_types=sqlite3.PARSE_DECLTYPES)
cur = con.cursor()
cur.execute("create table test(p point)")

cur.execute("insert into test(p) values (?)", (p,))
cur.execute("select p from test")
print("with declared types:", cur.fetchone()[0])
cur.close()
con.close()

#######################
# 1) 열 이름 사용하기
con = sqlite3.connect(":memory:", detect_types=sqlite3.PARSE_COLNAMES)
cur = con.cursor()
cur.execute("create table test(p)")

cur.execute("insert into test(p) values (?)", (p,))
cur.execute('select p as "p [point]" from test')
print("with column names:", cur.fetchone()[0])
cur.close()
con.close()

기본 어댑터와 변환기

datetime 모듈의 date와 datetime 형에 대한 기본 어댑터가 있습니다. 이것들은 ISO 날짜/ISO 타임스탬프로 SQLite로 보내집니다.

기본 변환기는 datetime.date는 "date"라는 이름으로, datetime.datetime은 "timestamp"라는 이름으로 등록됩니다.

이런 방법으로, 대부분 추가 작업 없이 파이썬의 날짜/타임스탬프를 사용할 수 있습니다. 어댑터의 형식은 실험적인 SQLite 날짜/시간 함수와도 호환됩니다.

다음 예제는 이를 보여줍니다.

import sqlite3
import datetime

con = sqlite3.connect(":memory:", detect_types=sqlite3.PARSE_DECLTYPES|sqlite3.PARSE_COLNAMES)
cur = con.cursor()
cur.execute("create table test(d date, ts timestamp)")

today = datetime.date.today()
now = datetime.datetime.now()

cur.execute("insert into test(d, ts) values (?, ?)", (today, now))
cur.execute("select d, ts from test")
row = cur.fetchone()
print(today, "=>", row[0], type(row[0]))
print(now, "=>", row[1], type(row[1]))

cur.execute('select current_date as "d [date]", current_timestamp as "ts [timestamp]"')
row = cur.fetchone()
print("current_date", row[0], type(row[0]))
print("current_timestamp", row[1], type(row[1]))

con.close()

SQLite에 저장된 타임스탬프가 6자리보다 긴 소수부가 있으면, 그 값은 타임스탬프 변환기에 의해 마이크로초 정밀도로 잘립니다.

트랜잭션 제어

하부 sqlite3 라이브러리는 기본적으로 autocommit 모드로 작동하지만, 파이썬 sqlite3 모듈은 기본적으로 그렇지 않습니다.

autocommit 모드는 데이터베이스를 수정하는 명령문이 즉시 적용됨을 뜻합니다. BEGIN 이나 SAVEPOINT 문은 autocommit 모드를 비활성화하고, 가장 바깥쪽 트랜잭션을 끝내는 COMMIT, ROLLBACK 또는 RELEASEautocommit 모드를 다시 켭니다.

기본적으로 파이썬 sqlite3 모듈은 데이터 조작 언어(DML - Data Modification Language) 문 (즉, INSERT/UPDATE/DELETE/REPLACE) 앞에 암묵적으로 BEGIN 문을 넣습니다.

connect() 호출의 isolation_level 매개 변수를 통해, 또는 연결의 isolation_level 프로퍼티를 통해, sqlite3가 묵시적으로 실행하는 BEGIN 문의 종류를 제어할 수 있습니다. isolation_level을 지정하지 않으면, 단순한 BEGIN이 사용되며, 이는 DEFERRED를 지정하는 것과 같습니다. 가능한 다른 값은 IMMEDIATEEXCLUSIVE입니다.

flowdas

DEFERREDBEGIN 문이 실행될 때 록을 만들지 않고, 실제로 읽거나 쓰는 시점에 록을 만듭니다. 반면에 IMMEDIATEBEGIN 문에서 즉시 록을 만듭니다. 두 경우 모두 다른 연결에서 여전히 데이터베이스를 읽을 수 있습니다. 하지만, EXCLUSIVEIMMEDIATE처럼 BEGIN 문에서 즉시 록을 만드는데, 이때는 다른 연결에서도 읽기가 금지됩니다.

isolation_levelNone로 설정하여 sqlite3 모듈의 묵시적 트랜잭션 관리를 비활성화할 수 있습니다. 그러면 하부 sqlite3 라이브러리가 autocommit 모드로 작동합니다. 그런 다음 코드에서 BEGIN, ROLLBACK, SAVEPOINTRELEASE 문을 명시적으로 실행하여 트랜잭션 상태를 완전히 제어할 수 있습니다.

버전 3.6에서 변경: sqlite3는 DDL 문 앞에서 열린 트랜잭션을 묵시적으로 커밋했습니다. 더는 그렇지 않습니다.

효율적으로 sqlite3 사용하기

바로 가기 메서드 사용하기

Connection 객체의 비표준 execute(), executemany()executescript() 메서드를 사용하면, (종종 불필요한) Cursor 객체를 명시적으로 만들 필요가 없으므로, 코드를 더 간결하게 작성할 수 있습니다. 대신, Cursor 객체가 묵시적으로 만들어지며 이러한 바로 가기 메서드는 커서 객체를 반환합니다. 이런 방법으로, Connection 객체에 대한 단일 호출만 사용하여 SELECT 문을 실행하고 직접 이터레이트할 수 있습니다.

import sqlite3

persons = [
    ("Hugo", "Boss"),
    ("Calvin", "Klein")
    ]

con = sqlite3.connect(":memory:")

# 테이블을 만듭니다
con.execute("create table person(firstname, lastname)")

# 테이블을 채웁니다
con.executemany("insert into person(firstname, lastname) values (?, ?)", persons)

# 테이블의 내용을 인쇄합니다
for row in con.execute("select firstname, lastname from person"):
    print(row)

print("I just deleted", con.execute("delete from person").rowcount, "rows")

# close is not a shortcut method and it's not called automatically,
# so the connection object should be closed manually
con.close()

인덱스 대신 이름으로 열 액세스하기

sqlite3 모듈의 유용한 기능 중 하나는 행 팩토리로 사용하도록 설계된 내장 sqlite3.Row 클래스입니다.

이 클래스로 감싼 행은 인덱스(튜플처럼)와 대소 문자를 구분하지 않는 이름으로 액세스할 수 있습니다:

import sqlite3

con = sqlite3.connect(":memory:")
con.row_factory = sqlite3.Row

cur = con.cursor()
cur.execute("select 'John' as name, 42 as age")
for row in cur:
    assert row[0] == row["name"]
    assert row["name"] == row["nAmE"]
    assert row[1] == row["age"]
    assert row[1] == row["AgE"]

con.close()

컨텍스트 관리자로 연결 사용하기

연결 객체는 트랜잭션을 자동으로 커밋하거나 롤백하는 컨텍스트 관리자로 사용할 수 있습니다. 예외가 발생하면, 트랜잭션이 롤백 됩니다; 그렇지 않으면 트랜잭션이 커밋 됩니다:

import sqlite3

con = sqlite3.connect(":memory:")
con.execute("create table person (id integer primary key, firstname varchar unique)")

# 성공적입니다, con.commit()이 자동으로 나중에 호출됩니다
with con:
    con.execute("insert into person(firstname) values (?)", ("Joe",))

# with 블록이 예외로 끝난 후에 con.rollback()이 호출됩니다, 예외는 여전히 발생하고, 잡아야 합니다
try:
    with con:
        con.execute("insert into person(firstname) values (?)", ("Joe",))
except sqlite3.IntegrityError:
    print("couldn't add Joe twice")

# Connection object used as context manager only commits or rollbacks transactions,
# so the connection object should be closed manually
con.close()

일반적인 문제

다중 스레드

이전 SQLite 버전에서는 스레드 간에 연결을 공유하는 데 문제가 있었습니다. 이것이 파이썬 모듈이 스레드 간에 연결과 커서를 공유하도록 허용하지 않는 이유입니다. 여전히 그렇게 하려고 하면 실행 시간에 예외가 발생합니다.

유일한 예외는 interrupt() 메서드를 호출하는 것입니다. 이 메서드는 다른 스레드에서 호출해야만 합니다.

각주

1(1,2)

기본적으로 sqlite3 모듈은 로드 가능한 확장을 지원하도록 빌드되지 않습니다. 일부 플랫폼(특히 맥 OS X)에는 이 기능 없이 컴파일된 SQLite 라이브러리가 있기 때문입니다. 로드 가능한 확장 지원을 받으려면, configure에 --enable-loadable-sqlite-extensions를 전달해야 합니다.