"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()

   # Create table
   c.execute('''CREATE TABLE stocks
                (date text, trans text, symbol text, qty real, price real)''')

   # Insert a row of data
   c.execute("INSERT INTO stocks VALUES ('2006-01-05','BUY','RHAT',100,35.14)")

   # Save (commit) the changes
   conn.commit()

   # We can also close the connection if we are done with it.
   # Just be sure any changes have been committed or they will be lost.
   conn.close()

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

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

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

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

   # Never do this -- insecure!
   symbol = 'RHAT'
   c.execute("SELECT * FROM stocks WHERE symbol = '%s'" % symbol)

   # Do this instead
   t = ('RHAT',)
   c.execute('SELECT * FROM stocks WHERE symbol=?', t)
   print(c.fetchone())

   # Larger example that inserts many records at a time
   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.


모듈 함수와 상수
================

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* 매개 변수에 사용됩니다.

   Setting this makes the SQLite interface parse the column name for
   each column it returns.  It will look for a string formed [mytype]
   in there, and then decide that 'mytype' is the type of the column.
   It will try to find an entry of 'mytype' in the converters
   dictionary and then use the converter function found there to
   return the value. The column name found in "Cursor.description"
   does not include the type, i. e. if you use something like "'as
   "Expiration date [datetime]"'" in your SQL, then we will parse out
   everything until the first "'['" for the column name and strip the
   preceeding space: the column name would simply be "Expiration
   date".

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

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

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

   데이터베이스가 여러 연결을 통해 액세스 되고, 프로세스 중 하나가 데
   이터베이스를 수정할 때, 해당 트랜잭션이 커밋될 때까지 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_DECLTYPES"와 "PARSE_COLNAMES"의 조합으로 설정하여 형 감지를
   켤 수 있습니다.

   기본적으로 *check_same_thread*는 "True"며, 만들고 있는 스레드 만 이
   연결을 사용할 수 있습니다. "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에서 찾을 수 있습니다.

   버전 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 용 셸을 만드는데 사용할 수 있습니다
   :

      # A minimal SQLite shell for experiments

      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) 콜백 등에서는 트레이스백을 얻지 못합니다. 디버깅하려면
   *flag*를 "True"로 설정하여 이 함수를 호출할 수 있습니다. 그러면,
   "sys.stderr"로 콜백의 트레이스백을 얻게 됩니다. 기능을 다시 비활성
   화하려면 "False"를 사용하십시오.


Connection 객체
===============

class sqlite3.Connection

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

   isolation_level

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

   in_transaction

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

      버전 3.2에 추가.

   cursor(factory=Cursor)

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

   commit()

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

   rollback()

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

   close()

      데이터베이스 연결을 닫습니다. 자동으로 "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)

      나중에 함수 이름 *name*으로 SQL 문에서 사용할 수 있는 사용자 정
      의 함수를 만듭니다. *num_params*는 함수가 받아들이는 매개 변수의
      수입니다 (*num_params*가 -1이면 함수는 임의의 인자를 취할 수 있
      습니다). *func*는 SQL 함수로 호출되는 파이썬 콜러블입니다.

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

      예:

         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)

      지정된 *name* 과 *callable*로 정렬법(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를 갱신하는데 사용할
      수 있습니다.

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

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

   set_trace_callback(trace_callback)

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

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

      "None"을 *trace_callback*로 전달하면 추적 콜백을 비활성화합니다.

      버전 3.3에 추가.

   enable_load_extension(enabled)

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

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

      버전 3.2에 추가.

         import sqlite3

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

         # enable extension loading
         con.enable_load_extension(True)

         # Load the fulltext search extension
         con.execute("select load_extension('./fts3.so')")

         # alternatively you can load the extension using an API call:
         # con.load_extension("./fts3.so")

         # disable extension loading again
         con.enable_load_extension(False)

         # example from SQLite wiki
         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"

         # by default, rows are returned as Unicode
         cur.execute("select ?", (AUSTRIA,))
         row = cur.fetchone()
         assert row[0] == AUSTRIA

         # but we can make sqlite3 always return bytestrings ...
         con.text_factory = bytes
         cur.execute("select ?", (AUSTRIA,))
         row = cur.fetchone()
         assert type(row[0]) is bytes
         # the bytestrings will be encoded in UTF-8, unless you stored garbage in the
         # database ...
         assert row[0] == AUSTRIA.encode("utf-8")

         # we can also implement a custom text_factory ...
         # here we implement one that appends "foo" to all strings
         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" 명령과 같은 기능을
      제공합니다.

      예:

         # Convert file existing_db.db to SQL dump file 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" 인스턴스여야 합니다.

      기본적으로, 또는 *pages*가 "0" 이나 음의 정수이면, 전체 데이터베
      이스가 단일 단계로 복사됩니다; 그렇지 않으면 이 메서드는 한 번에
      최대 *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

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

   execute(sql[, parameters])

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

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

         import sqlite3

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

         who = "Yeltsin"
         age = 72

         # This is the qmark style:
         cur.execute("insert into people values (?, ?)", (who, age))

         # And this is the named style:
         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)

      시퀀스 *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_script*는 "str"의 인스턴스가 될 수 있습니다.

      예:

         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()

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

   fetchmany(size=cursor.arraysize)

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

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

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

   fetchall()

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

   close()

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

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

   rowcount

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

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

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

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

   lastrowid

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

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

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

   arraysize

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

   description

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

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

   connection

      이 읽기 전용 어트리뷰트는 "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

   "Exception"의 서브 클래스.

exception sqlite3.Error

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

exception sqlite3.DatabaseError

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

exception sqlite3.IntegrityError

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

exception sqlite3.ProgrammingError

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

exception sqlite3.OperationalError

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

exception sqlite3.NotSupportedError

   데이터베이스에서 지원하지 않는 메서드나 데이터베이스 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 형을 다른 파이썬 형으로 변환할
수 있습니다.


어댑터를 사용하여 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)" 메서드를 제공해야 합니다.
매개 변수 *protocol*은 "PrepareProtocol"이 됩니다.

   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.date" 와
"datetime.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_DECLTYPES" 와
"PARSE_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)

   # Register the adapter
   sqlite3.register_adapter(Point, adapt_point)

   # Register the converter
   sqlite3.register_converter("point", convert_point)

   p = Point(4.0, -3.2)

   #########################
   # 1) Using declared types
   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) Using column names
   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" 또는 "RELEASE"는
"autocommit" 모드를 다시 켭니다.

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

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

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

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


효율적으로 "sqlite3" 사용하기
=============================


바로 가기 메서드 사용하기
-------------------------

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

   import sqlite3

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

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

   # Create the table
   con.execute("create table person(firstname, lastname)")

   # Fill the table
   con.executemany("insert into person(firstname, lastname) values (?, ?)", persons)

   # Print the table contents
   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)")

   # Successful, con.commit() is called automatically afterwards
   with con:
       con.execute("insert into person(firstname) values (?)", ("Joe",))

   # con.rollback() is called after the with block finishes with an exception, the
   # exception is still raised and must be caught
   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] 기본적으로 sqlite3 모듈은 로드 가능한 확장을 지원하도록 빌드되지
    않습니다. 일부 플랫폼(특히 맥 OS X)에는 이 기능 없이 컴파일된
    SQLite 라이브러리가 있기 때문입니다. 로드 가능한 확장 지원을 받으
    려면, configure에 --enable-loadable-sqlite-extensions를 전달해야
    합니다.
