SQLite는 가장 인기 있는 관계형 데이터 베이스 관리 시스템(RDBMS) 중 하나입니다. 가벼운 특성을 가지고 있으며, 시스템에 많은 공간을 사용하지 않습니다. 그 가장 좋은 특징 之一는 서버를 사용하지 않는다는 것입니다. 따라서 SQLite를 사용하기 위해서는 따로 설치하거나 관리할 수 있는 서버가 없어야 합니다.
대신에, 모든 것을 당신의 컴퓨터上的 간단한 파일로 저장합니다. 또한 어느 것도 Konfiguration을 요구하지 않으며, 어렵고 복잡한 세팅 과정이 없으므로 初心者들과 小编의 프로젝트에 완벽하게 적용되ます.
SQLite는 小编의 应用 에 가장 좋은 선택입니다. 이를 사용하는 것이 간단하며, 빨라며 더 큰 데이터베이스와 마찬가지로 대부분의 任务을 처리할 수 있습니다. 그러나 extra software의 관리를 해야하는 번거로움이 없습니다.
이 튜토리얼에서는 Python을 사용하여 SQLite와 일하는 방법을 배울 것입니다. 이 튜토리얼에서 다음을 涵蓋 할 것입니다:
이 튜토리얼은 복잡한 설정을 건너는 것 없이 데이터베이스에 대해 시작하고자 하는 누구에게도 완벽하다.
Python 환경 설정하기
SQLite를 사용하기 전에, Python 환경이 준비되었는지 확인해보자. 어떻게 모든 것을 설정하는지 여기서 배워보자.
Python 설치하기
아직 Python을 시스템에 설치하지 않았다면, 공식 Python 웹사이트에서 다운로드 할 수 있다. 您的Operating System (Windows, macOS, or Linux)의 설치 指导서를 따라야 한다.
Python이 설치되었는지 확인하려면, 终端(또는 명령어 prompt)을 개시하고 다음과 같이 입력하면 된다:
python --version
이것은 현재 설치된 Python의 Current Version을 보여준다. 설치되어 있지 않다면, Python 웹사이트의 指导서를 따라야 한다.
SQLite3 모듈 설치하기
好消息은 SQLite3이 Python에 내장되어 있다는 것입니다! 따라서 따로 설치할 必要가 없습니다. 표준 Python 라이브러리에 포함되어 있기 때문에 즉刻に 사용할 수 있습니다. 이것은 추가적인 세팅없이 시작할 수 있는 것을 의미합니다.
가상 환경 생성하는 方法(선택적으로 하지만 推奨적인 것)
每个 프로젝트에 대해 가상 환경을 생성하는 것이 좋은 아이디어입니다. 의존성을 정리하는 것입니다. 가상 환경은 전체 Python 설치를 영향 안 받는 чисто한 slate가 되어 있습니다.
가상 환경을 생성하기 위해서는 다음과 같은 단계를 따라야 합니다:
-
まず, terminal나 명령어 띄어쓰기를 열고 당신이 프로젝트를 생성하고자 하는 디렉터리로 이동합니다.
-
가상 환경을 생성하는 것은 다음과 같은 명령어를 실행합니다.
python -m venv env
여기서 env
는 가상 환경의 이름입니다. 이름을 지정할 수 있습니다.
- 가상 환경을 활성화하십시오:
# Windows에서 사용하는 명령어
env\Scripts\activate
# macOS/Linux에서 사용하는 명령어:
env/bin/activate
가상 환경을 활성화한 후에, terminalshell prompt가 변경되는 것을 발견할 수 있습니다. 이것은 가상 환경의 이름을 보여줍니다. 이제 이 안에서 작업하고 있음을 의미합니다.
필요한 라이브러리를 설치하는 것
이 프로젝트를 위해 额外的な ibrary들이 필요합니다. 특정히, 다음과 같이 사용할 것입니다:
-
pandas
: 이것은 Advanced use cases에서 유용한 탭ular 형식의 데이터를 처리하고 보이는 옵션적인 ibrary입니다. -
faker
: 이 ibrary은 arbitrary names and addresses과 같은 가짜 데이터를 생성하여 이를 우리의 데이터베이스에 Unit testing 目的로 삽입할 수 있도록 도와줍니다.
pandas
과 faker
를 설치하는 데에 다음과 같은 명령어를 simply run하即可:
pip install pandas faker
이것은 가상 환경에 pandas
와 faker
를 설치합니다. 이렇게 하면 이를 이용해 Python에서 SQLite 데이터베이스를 생성하고 관리할 준비가 되었습니다!
SQLite 데이터베이스를 어떻게 만들呢?
DB는 데이터를 轻松하게 存取하고 관리하는 구조화된 방법을 제공하는 것이며, 이는 ein digital filing system가 같습니다. 이를 이용해 simply app 또는 더 複雑한 system에서 대량의 데이터를 効率的하게 보관할 수 있습니다. 데이터베이스는 데이터를 보관하기 위해 表(tables)를 사용하며, 行(rows)와 열(columns)가 individual records과 그 특성을 표현합니다.
SQLite 데이터베이스는 어떻게 동작呢?
대부분의 데이터베이스 시스템과 달리 SQLite는 서버 없는 데이터베이스입니다. 이는 서버를 설정하거나 관리할 필요가 없어 가벼우며 사용하는 것이 간편하게 만들어집니다. 모든 데이터는 컴퓨터의 单个 파일에 저장되어 이를 간편하게 이동하거나 共有하거나 备份할 수 있습니다. simplicity 그리고 SQLite는 単純하지만 일반적인 데이터베이스 任务을 처리하는 용이한 기능을 갖추고 있으며 모바일 앱, 내장 시스템, 以及 中小型 프로젝트에 널리 사용되고 있습니다.
새 SQLite 데이터베이스 생성하는 방법
Python의 sqlite3
라이브러리를 사용하여 새 SQLite 데이터베이스에 대한 이해를 키울 때는 어떻게 인터랙트를 할 수 있는지 알아봅시다.
데이터베이스에 연결하는 것
sqlite3
는 이미 설치되어 있으므로 Python 스크립트에서 mport 해야만 합니다. 새로운 데이터베이스를 생성하거나 기존의 데이터베이스와 연결하는 것은 sqlite3.connect()
方法的을 사용합니다. 이 方法은 데이터베이스 파일의 이름을 인자로 사용합니다. 파일이 존재하지 않는다면 SQLite는 자동으로 생성합니다.
import sqlite3
# SQLite 데이터베이스에 연결하거나 존재하지 않으면 생성한다
connection = sqlite3.connect('my_database.db')
이 예에서, 스크립트의 同样 디렉터리에 my_database.db
이라는 파일이 생성됩니다. 이미 파일이 존재하면 SQLite는 그 파일에 연결하는 것을 시도합니다.
커서 생성
연결을 얻었으면 다음 단계는 커서 오브젝트를 생성하는 것입니다. 커서는 데이터베이스에 SQL 명령과 쿼리를 실행하는 义务를 갖추고 있습니다.
# 커서 오브젝트를 생성합니다
cursor = connection.cursor()
연결을 닫는 것
작업을 마친 후에는 데이터베이스 연결을 닫는 것이 중요하며, 리소스를 解放시키는 것입니다. 다음과 같은 명령어를 사용하여 연결을 닫을 수 있습니다.
# 데이터베이스 연결 닫기
connection.close()
그러나 모든 작업을 끝내고 연결을 닫는 것이 좋습니다.
Python 스크립트를 실행하면, 현재 작업 디렉터리에 my_database.db
라는 이름의 파일이 생성됩니다. SQLite 데이터베이스를 성공적으로 만들었습니다!
上下文 관리자를 사용하여 연결을 열고 닫는 方法
Python은 with
语句(上下文 관리자라고도 불립니다)를 사용하여 데이터 베이스 연결을 더 효율적으로 하고 清洁하게 처리할 수 있는 것을 제공합니다. with
语句은 데이터베이스 연산 중 에러가 발생하더라도 연결을 제대로 닫는 것을 보장하며, connection.close()
를 수동으로 호출할 필요가 없습니다.
데이터베이스 연결을 처리하는 것이 어떻게 되는지 다음과 같이 하실 수 있습니다.
import sqlite3
# 과정 1: 'with'를 사용하여 데이터베이스에 연결하거나(또는 생성하고) 작업 끝나면 자동으로 닫습니다.
with sqlite3.connect('my_database.db') as connection:
# 과정 2: 데이터베이스와 대화를 나누기 위한 游標(cursor) 객체를 생성합니다.
cursor = connection.cursor()
print("Database created and connected successfully!")
# 연결을 닫는 것이 아니라; 이를 자동으로 하고 있습니다!
이제 forthcoming code examples에서 저희는 efficiently manage database connections하기 위해 with
statement을 사용할 것입니다. 이렇게 하면 코드를 더 concise하게 하고 관리하기가 더 容易하게 만들 것입니다.
Database Tables 만들기
SQLite database를 만들고 그것과 연결한 다음, 다음 단계는 databases内部에 tables를 만들어야 합니다. 이곳은 우리의 데이터를 rows(records)와 columns(attributes)로 organized하여 저장할 곳입니다. 이 예제에서는 이후 섹션에서 다시 사용할 수 있는 학생 정보를 저장하기 위해 Students
라는 table를 만듭니다.
table를 만들기 위해서는 SQL의 CREATE TABLE
statement을 사용합니다. 이 명령은 table의 구조를 지정하며, 각 列(column)의 이름과 각 列(column)의 data type를 지정합니다.
이 예에서는 다음과 같은 필드를持つ Students
table를 만들기 위한 간단한 SQL 명령을 다음과 같이 写합니다 :
-
id
: 각 student exclusive identifier (integer). -
name: student의 name (text).
-
age: student의 age (integer).
-
email: student의 email address (text).
이 表을 만들기 위한 SQL command은 다음과 같습니다 :
CREATE TABLE Students (
id INTEGER PRIMARY KEY AUTOINCREMENT,
name TEXT NOT NULL,
age INTEGER,
email TEXT
);
CREATE TABLE
SQL 명령을 파이썬에서 sqlite3
라이브러리를 사용하여 실행할 수 있습니다. 어떻게 해야 하는지 보겠습니다.
import sqlite3
# 'with'를 사용하여 SQLite 데이터베이스에 연결하고, 작업 완료 시 자동으로 연결을 끊습니다.
with sqlite3.connect('my_database.db') as connection:
# 커서 오브젝트를 생성합니다.
cursor = connection.cursor()
# Students 테이블을 생성하기 위한 SQL 명령을 기록합니다.
create_table_query = '''
CREATE TABLE IF NOT EXISTS Students (
id INTEGER PRIMARY KEY AUTOINCREMENT,
name TEXT NOT NULL,
age INTEGER,
email TEXT
);
'''
# SQL 명령을 실행합니다.
cursor.execute(create_table_query)
# 변경사항을 읽込합니다.
connection.commit()
# 확인 메시지를 인쇄합니다.
print("Table 'Students' created successfully!")
-
IF NOT EXISTS
: 이 옵션은 이미 테이블이 존재하지 않는다면 테이블을 생성하는 것을 보장합니다. 이전에 테이블이 생성되었을 때 에러가 발생하는 것을 防止합니다. -
connection.commit()
: 이 메서드는 데이터베이스에 변경사항을 저장합니다.
위의 파이썬 코드를 실행하면 my_database.db
데이터베이스 파일에 Students
테이블을 생성합니다. 终端에 테이블이 성공적으로 생성되었음을 인쇄하는 메시지를 볼 수 있을 것입니다.
시각 스텍 코드를 사용하면 SQLite Viewer 확장 기능을 설치하여 SQLite 데이터베이스를 보기 위해 사용할 수 있습니다.
SQLite에서 지원하는 several data types exist, and we need to understand them when defining our tables. 여기에서는 SQLite data types와 Python types에서 어떻게 매핑되는지 빠른 개요를 제시합니다.
SQLite Data Type | Description | Python Equivalent |
INTEGER | Integers | int |
TEXT | String text | str |
REAL | Floating-point numbers | float |
BLOB | Binary data (e.g., images, files) | bytes |
NULL | Represents no value or missing data | None |
In our Students
table:
-
id
is of typeINTEGER
, which maps to Python’sint
. -
name
andemail
are of typeTEXT
, which map to Python’sstr
. -
age
도INTEGER
형식이며 Python의int
와 매핑됩니다.
테이블에 데이터 삽입하는 방법
Students
테이블이 생성되었으므로 데이터를 데이터베이스에 삽입할 차례입니다. 이 섹션에서는 파이썬과 SQLite로 단일 및 다중 레코드를 삽입하는 방법과 파라미터화된 쿼리를 사용하여 SQL 삽입 같은 공통 보안 이슈를 피하는 방법을 다룰 것입니다.
단일 레코드 삽입 방법
데이터베이스에 데이터를 삽입하려면 INSERT INTO
SQL 명령을 사용합니다. 우선 Students
테이블에 단일 레코드를 삽입해봅시다.
단일 레코드 삽입을 위한 기본 SQL 문법은 다음과 같습니다:
INSERT INTO Students (name, age, email)
VALUES ('John Doe', 20, '[email protected]');
그러나 파이썬 스크립트에서 하드코딩된 값을 사용하여 직접 SQL을 작성하는 대신 파라미터화된 쿼리를 사용하여 코드를 더욱 안전하고 유연하게 만들 것입니다. 파라미터화된 쿼리는 해로운 입력을 전달하여 SQL 쿼리를 조작할 수 있는 공통적인 공격인 SQL 삽입을 방지하는 데 도움이 됩니다.
파라미터화된 쿼리를 사용하여 Students
테이블에 단일 레코드를 삽입하는 방법은 다음과 같습니다:
import sqlite3
# 'with' 关键字로 자동으로 연결 OPEN/CLOSE
with sqlite3.connect('my_database.db') as connection:
cursor = connection.cursor()
# 학생 테이블에 레코드 삽입
insert_query = '''
INSERT INTO Students (name, age, email)
VALUES (?, ?, ?);
'''
student_data = ('Jane Doe', 23, '[email protected]')
cursor.execute(insert_query, student_data)
# 자동으로 변경 사항 커밋
connection.commit()
# connection.close(); 호출 필요 없이 자동으로 처리됩니다!
print("Record inserted successfully!")
The ?
홀더는 테이블에 삽입되는 값을 represent하는 것입니다. 실제 값은 cursor.execute()
方法的에서 튜플 (student_data
)로 전달되ます.
多条记录插入하는 方法
한번에 多条记录插入하고자 하면, Python에서 executemany()
方法을 사용할 수 있습니다. 이 方法은 각 레코드를 represent하는 튜플의 목록을 받습니다.
我们的例子를 더 대 dynamize하기 위해, Faker
库를 사용하여 랜덤한 학생 데이터를 생성할 수 있습니다. 이것은 테스트하고 실제 세계의 상황을 仿真하는 것이 유용합니다.
from faker import Faker
import sqlite3
# Faker 初期化
fake = Faker(['en_IN'])
# 'with' 关键字로 자동으로 연결 OPEN/CLOSE
with sqlite3.connect('my_database.db') as connection:
cursor = connection.cursor()
# 학생 테이블에 레코드 삽입
insert_query = '''
INSERT INTO Students (name, age, email)
VALUES (?, ?, ?);
'''
students_data = [(fake.name(), fake.random_int(
min=18, max=25), fake.email()) for _ in range(5)]
# 多条记录 쿼리 실행
cursor.executemany(insert_query, students_data)
# 변경 사항 커밋
connection.commit()
# 확인 massage를 인쇄
print("Fake student records inserted successfully!")
이 코드에서:
-
Faker()
Faker()
는 학생들의 Random 이름, 연령, 이메일을 생성합니다. 지역([‘en_IN’]
)을 전달하는 것은 선택적입니다. -
cursor.executemany()
: 이 메서드는 우리가 한 번에 多条记录을 삽입할 수 있게 해줍니다. 이를 통해 코드의 효율성이 더욱 향상됩니다. -
students_data
: 각 튜플은 한 학생의 데이터를 表현하는 튜플의 리스트입니다.
일반적인 문제 처리: SQL Injection
SQL Injection은 공격자가 harmful input을 제공하여 SQL 쿼리를 삽입하거나 조작할 수 있는 보안 취약성입니다. 例如, 공격자는 '; DROP TABLE Students; --
과 같은 코드를 삽입하여 테이블을 지우려고 하는 것が 있습니다.
위에서 보여주고 있는 parameterized queries를 사용하면 이러한 문제를 해결할 수 있습니다. parameterized queries에서의 ?
占位符은 입력 값을 데이터로 처리하고 SQL 명령의 일부가 아닙니다. 이렇게 恶意的 code가 실행되는 것을 방지합니다.
데이터를 쿼리하는 方法
이제 Students
테이블에 一些 데이터를 삽입했으며, 이 테이블에서 데이터를 가져오는 방법을 배우겠습니다. 파이썬에서 데이터를 가져오는 다양한 方法을 探ります including fetchone()
, fetchall()
, and fetchmany()
methods.
테이블에서 데이터를 쿼리하는 것은 SELECT
문을 사용합니다. 以下 SQL 명령어는 Students
테이블에서 모든 열을 선택합니다:
SELECT * FROM Students;
이 명령어는 Students
테이블에서 모든 레코드와 열을 가져옵니다. 우리는 이 SELECT
문을 파이썬에서 실행하고 결과를 가져올 수 있습니다.
모든 레코드를 가져오는 方法
以下 과정을 통해 Students
테이블에서 모든 레코드를 가져올 수 있습니다:
import sqlite3
# SQLite 데이터베이스에 'with'를 사용하여 연결
with sqlite3.connect('my_database.db') as connection:
# 커서 오브젝트를 생성
cursor = connection.cursor()
# Students
테이블에서 모든 레코드를 선택하는 SQL 명령어를 작성
select_query = "SELECT * FROM Students;"
# SQL 명령어를 실행
cursor.execute(select_query)
# 모든 레코드를 가져옵니다
all_students = cursor.fetchall()
# 终端에 결과를 표시합니다
print("All Students:")
for student in all_students:
print(student)
이 예에서 fetchall()
方法은 쿼리로 돌아온 모든 行을 튜플의 목록으로 가져와줍니다.
All Students:
(1, 'Jane Doe', 23, '[email protected]')
(2, 'Bahadurjit Sabharwal', 18, '[email protected]')
(3, 'Zayyan Arya', 20, '[email protected]')
(4, 'Hemani Shukla', 18, '[email protected]')
(5, 'Warda Kara', 20, '[email protected]')
(6, 'Mitali Nazareth', 19, '[email protected]')
하나의 레코드 only 가져오기
하나의 레코드만 가져오고자 하면 fetchone()
方法을 사용할 수 있습니다:
import sqlite3
SQLite 데이터베이스에 'with'를 사용하여 연결합니다
with sqlite3.connect('my_database.db') as connection:
커서 객체를 생성합니다
cursor = connection.cursor()
Students 테이블에서 모든 레코드를 선택하는 SQL 명령을 작성합니다
select_query = "SELECT * FROM Students;"
SQL 명령을 실행합니다
cursor.execute(select_query)
하나의 레코드를 가져옵니다
student = cursor.fetchone()
결과를 출력합니다
print("First Student:")
print(student)
출력:
First Student:
(1, 'Jane Doe', 23, '[email protected]')
여러 레코드를 가져오는 방법
특정数量的 레코드를 가져오려면 fetchmany(size)
를 사용할 수 있습니다:
import sqlite3
SQLite 데이터베이스에 'with'를 사용하여 연결합니다
with sqlite3.connect('my_database.db') as connection:
커서 객체를 생성합니다
cursor = connection.cursor()
Students 테이블에서 모든 레코드를 선택하는 SQL 명령을 작성합니다
select_query = "SELECT * FROM Students;"
SQL 명령을 실행합니다
cursor.execute(select_query)
세 개의 레코드를 가져옵니다
three_students = cursor.fetchmany(3)
결과를 출력합니다
print("Three Students:")
for student in three_students:
print(student)
출력:
Three Students:
(1, 'Jane Doe', 23, '[email protected]')
(2, 'Bahadurjit Sabharwal', 18, '[email protected]')
(3, 'Zayyan Arya', 20, '[email protected]')
pandas
를 사용하여 데이터 표시를 향상시키는 방법
데이터 표시를 향상시키기 위해 pandas
라이브러리를 사용하여 쿼리 결과로 DataFrame
를 만들 수 있습니다. 이렇게 하면 데이터를 조작하고 시각화하는 것이 더 쉽습니다.
모든 레코드를 가져와 pandas DataFrame으로 표시하는 방법은 다음과 같습니다:
import sqlite3
import pandas as pd
# SQLite 데이터베이스에 연결하기 위해 'with' 사용
with sqlite3.connect('my_database.db') as connection:
# Student 테이블에 있는 모든 레코드를 선택하는 SQL 명령어 쓰기
select_query = "SELECT * FROM Students;"
# pandas를 사용하여 SQL 쿼리를 데이터프레임에 的確히 읽기
df = pd.read_sql_query(select_query, connection)
# 데이터프레임을 표시하기
print("All Students as DataFrame:")
print(df)
생성 결과:
All Students as DataFrame:
id name age email
0 1 Jane Doe 23 [email protected]
1 2 Bahadurjit Sabharwal 18 [email protected]
2 3 Zayyan Arya 20 [email protected]
3 4 Hemani Shukla 18 [email protected]
4 5 Warda Kara 20 [email protected]
5 6 Mitali Nazareth 19 [email protected]
pd.read_sql_query()
함수는 SQL 쿼리를 실행하고 그 결과를 직접 pandas DataFrame로 리턴합니다.
데이터 갱신과 삭제
이 섹션에서, 우리는 Python에서 SQL 명령어를 사용하여 Students
테이블의 기존 레코드를 更新하고 레코드를 삭제할 方法을 배울 것입니다. 이것은 effective하게 데이터를 관리하고 유지하는 데 필요한 것입니다.
기존 레코드 갱신
데이터베이스에 기존 레코드를 수정하려면 SQL UPDATE
명령어를 사용합니다. 이 명령어는 지정된 조건에 따라 하나 이상의 行에 특정 열의 값을 변경할 수 있습니다.
例如, 학생의 나이를 更新하고자 하면, 이 SQL 명령어가 보입니다:
UPDATE Students
SET age = 21
WHERE name = 'Jane Doe';
이제, 우리는 Python 코드를 사용하여 Students
테이블에서 특정 학생의 나이를 更新하는 것을 배울 것입니다.
import sqlite3
# 'with' 关键字로 SQLite 데이터베이스에 연결하기
with sqlite3.connect('my_database.db') as connection:
cursor = connection.cursor()
# 학생의 나이를 更新하는 SQL 명령
update_query = '''
UPDATE Students
SET age = ?
WHERE name = ?;
'''
# 更新할 데이터
new_age = 21
student_name = 'Jane Doe'
# SQL 명령과 데이터로 실행
cursor.execute(update_query, (new_age, student_name))
# 변경사항을 저장하기 위해 커밋
connection.commit()
# 확인 消息를 打印
print(f"Updated age for {student_name} to {new_age}.")
이 예에서는 SQL 인젝션을 防范하기 위해 매개 변수 쿼리를 사용했습니다.
테이블에서 레코드를 삭제하는 方法
데이터베이스에서 레코드를 제거하려면 SQL DELETE
명령을 사용합니다. 이 명령은 지정한 조건에 따라 하나 이상의 行을 삭제할 수 있습니다.
例如, ‘Jane Doe’라는 학생을 삭제하려면 SQL 명령은 다음과 같습니다:
DELETE FROM Students
WHERE name = 'Jane Doe';
Python 코드를 사용하여 Students
테이블에서 특정 학생을 삭제하는 것을 시도하겠습니다.
import sqlite3
# 'with' 关键字로 SQLite 데이터베이스에 연결하기
with sqlite3.connect('my_database.db') as connection:
cursor = connection.cursor()
# 학생을 삭제하는 SQL 명령
delete_query = '''
DELETE FROM Students
WHERE name = ?;
'''
# 삭제할 학생의 이름
student_name = 'Jane Doe'
# 데이터로 SQL 명령을 실행
cursor.execute(delete_query, (student_name,))
# 변경사항을 저장하기 위해 커밋
connection.commit()
# 확인 消息를 打印
print(f"Deleted student record for {student_name}.")
중요한 고려 사항
-
조건: 레코드 更新 또는 삭제 할 때
WHERE
CLAUSE를 항상 사용하여 모든 行을 수정하거나 제거하지 않는 것을 防止する。WHERE
CLAUSE가 없으면, 명령어는 테이블의 모든 行에 영향을 미칠 수 있습니다. -
备份: 특히 생산 환경에서는 更新 또는 삭제 전에 데이터베이스를 备份하는 것이 좋은 惯例입니다.
Transaction 사용 방법
Transaction은 SQL opera tion의 하나 이상의 시퀀스로 가지고 있는 작업 단위로 취급되는 것입니다. 데이터베이스 contest에서는 다수의 작업을 모두 성공하거나 모두 실패하도록 실행할 수 있는 것이며, 이를 통해 데이터베이스가 에러나 예상치 못한 이슈로부터 일관성이 유지되는 것을 보장합니다.
例如, 두 개의 은행 계좌 사이에 현금을 이전하는 것이면 한 계좌의 차감과 다른 계좌의 credi t를 모두 성공하거나 실패하도록 하고 싶습니다. 하나의 작업이 실패하면 다른 것도 실행되지 않도록 일관성을 유지하는 것입니다.
Transaction을 사용하는 이유?
-
atomicity : 트랜잭션은 일련의 operatio들을 単独 単位として 처리하는 것을 보장합니다. 하나의 operatio가 실패하면, 모든 operatio가 データ베이스에 적용되지 않습니다.
-
consistency : 트랜잭션은 모든 규칙과 제약조건을 따를 때까지 データ베이스의 整eness를 유지하는 데 도움이 됩니다.
-
isolation : 각 트랜잭션은 다른 것들과 독립적으로 작동하여 의도치 않은 상호 영향을 방지합니다.
-
durability : 트랜잭션이 확정되면, 변경사항이 시스템 문제를 나타내도 永久的하게 유지됩니다.
Transaction을 언제 사용하는가?
다음과 같은 상황에서 Transaction을 사용해야 합니다:
-
일련의 관련 operatio를 모두 함께 성공하거나 실패하도록 수행합니다.
-
일관성과 정확성이 필요한 중요 data를 수정합니다.
-
finanical transactions 또는 데이터 이전과 같은 실수 가능한 작업과 함께 일어나는 것.
Python에서 Transaction을 어떻게 관리하는지.
SQLite에서는 BEGIN
, COMMIT
, ROLLBACK
명령을 사용하여 Transaction을 관리하나, Python의 sqlite3
모듈을 사용할 때는 연결 오브젝트를 통해 Transaction을 관리합니다.
Transaction은 SQL 문을 실행하면 암묵적으로 시작되며, Transaction을 명시적으로 시작하기 위해 BEGIN
명령을 사용할 수 있습니다.
cursor.execute("BEGIN;")
그러나 SQLite는 SQL 문을 실행할 때 자동으로 Transaction을 시작하므로, 수동으로 Transaction을 시작할 필요가 없습니다.
Transaction 期间에 생성한 모든 변경을 저장하려면 commit()
메서드를 사용합니다. 이는 모든 변경을 데이터 베이스에 영구적으로 적용합니다.
connection.commit()
이전에 제시한 예제에서 commit()
메서드를 이미 사용했습니다.
Transaction 期间에 발생한 에러가 있을 때, 변경을 되돌리고 싶다면 rollback()
메서드를 사용할 수 있습니다. 이는 Transaction을 시작한 후에 생성된 모든 변경을 취소합니다.
connection.rollback()
Python에서 Transaction 사용 예시.
세계적인 거래 사례를 설명하기 위해 Customers
라는 새로운 테이블을 생성하여 고객 계좌를 관리하도록 한다. 이 예에서는 각 고객이 balance
를 갖추고 있다고 가정한다. 이 테이블에 두 명의 고객을 추가하고 그들之间의 자금 이전 operatioin을 실행할 것이다.
まず Customers
테이블을 생성하고 두 명의 고객을 추가하는 것을 시도할 것이다 :
import sqlite3
#Customers 테이블 생성 및 두 고객 추가
with sqlite3.connect('my_database.db') as connection:
cursor = connection.cursor()
#Customers 테이블 생성
create_customers_table = '''
CREATE TABLE IF NOT EXISTS Customers (
id INTEGER PRIMARY KEY AUTOINCREMENT,
name TEXT NOT NULL UNIQUE,
balance REAL NOT NULL
);
'''
cursor.execute(create_customers_table)
#두 고객 추가
cursor.execute(
"INSERT INTO Customers (name, balance) VALUES (?, ?);", ('Ashutosh', 100.0))
cursor.execute(
"INSERT INTO Customers (name, balance) VALUES (?, ?);", ('Krishna', 50.0))
connection.commit()
이제 Ashutosh와 Krishna 사이로 자금 이전 operatioin을 실행하는 것을 시도할 것이다 :
import sqlite3
def transfer_funds(from_customer, to_customer, amount):
with sqlite3.connect('my_database.db') as connection:
cursor = connection.cursor()
try:
#transaction을 시작하십시오
cursor.execute("BEGIN;")
#보내는 사람의 금액을 빼십시오
cursor.execute(
"UPDATE Customers SET balance = balance - ? WHERE name = ?;", (amount, from_customer))
#받는 사람에게 금액을 추가하십시오
cursor.execute(
"UPDATE Customers SET balance = balance + ? WHERE name = ?;", (amount, to_customer))
#변경사항을 적용하십시오
connection.commit()
print(
f"Transferred {amount} from {from_customer} to {to_customer}.")
except Exception as e:
#에러가 발생하면,transaction을 allback하십시오
connection.rollback()
print(f"Transaction failed: {e}")
#사용 예
transfer_funds('Ashutosh', 'Krishna', 80.0)
이 예제에서는 우선 Customers
테이블을 생성하고, Ashutosh를 100₹로 Balance로 두 고객을 삽입했고, Krishna는 50₹로 Balance를 삽입했습니다. 그 다음 Ashutosh에서 Krishna로 80₹의 자금이 이전되었습니다. transactions를 사용하여 Ashutosh의 계좌에서 차감과 Krishna의 계좌에서 crediting가 단일 atomicity 操 作으로 실행되도록 보장했습니다. 이러한 방안으로 에러 발생 시 데이터 정확성을 유지할 수 있습니다. 이 이전 실패하면(예를 들어 자금이 부족한다면), 트랜잭션은 되돌릴 수 있으며 모두의 계좌를 변경하지 않습니다.
SQLite 쿼리 パフォーマンス 최적화를 위한 인덱싱
인덱싱은 데이터 베이스에서 쿼리 パフォーマン스를 改善시키는 강력한 기술입니다. 인덱스는 특정 열 값에 따라 行의 위치를 저장하는 데이터 구조로, книги의 뒷 部分에 있는 인덱스와 마찬가지로 빠르게 주제를 찾을 수 있습니다.
인덱스를 사용하지 않는다면, SQLite는 전체 테이블을 행 単位로 스캔하여 pertinent data를 찾기 위해, dataset이 커지는 것에 따라 inefficient가 되어가며, 인덱스를 사용하면 SQLite가 필요한 行을 직접 이동하여 쿼리 실행을 значитель히 加速시킵니다.
가짜 데이터로 데이터 베이스를 populte하는 方法
indexing의 영향을 effective하게 시험하기 위해서는 적절한 dataset size가 필요합니다. record를 수동으로 추가하는 것 보다는, faker
library를 사용하여 가짜 data를 빨라게 생성할 수 있습니다. 이 섹션에서는 Students
테이블에 10,000개의 가짜 record를 생성하고 삽입할 것입니다. 이렇게 실제 세계의 경우를 Simulate하여 database가 커지고 쿼리 パフォーマン스가 중요한 경우를 仿真하게 됩니다.
다음의 기록을 삽입하기 위해 executemany()
메소드를 사용할 것입니다:
import sqlite3
from faker import Faker
# Faker 라이브러리 초기화
fake = Faker(['en_IN'])
def insert_fake_students(num_records):
"""Generate and insert fake student data into the Students table."""
fake_data = [(fake.name(), fake.random_int(min=18, max=25),
fake.email()) for _ in range(num_records)]
# 데이터베이스 연결을 처리하기 위해 'with' 사용
with sqlite3.connect('my_database.db') as connection:
cursor = connection.cursor()
# Students 테이블에 가짜 데이터 삽입
cursor.executemany('''
INSERT INTO Students (name, age, email)
VALUES (?, ?, ?);
''', fake_data)
connection.commit()
print(f"{num_records} fake student records inserted successfully.")
# Students 테이블에 10,000개의 가짜 기록 삽입
insert_fake_students(10000)
이 스크립트를 실행하면 Students
테이블에 10,000개의 가짜 학생 기록이 추가됩니다. 다음 섹션에서는 데이터베이스를 조회하고 인덱싱이 있고 없을 때의 쿼리 성능을 비교할 것입니다.
인덱스 없이 쿼리하는 방법
이 섹션에서는 인덱스 없이 Students
테이블을 조회하여 SQLite가 최적화를 하지 않은 경우 어떻게 동작하는지 관찰합니다. 이를 통해 나중에 인덱스를 추가했을 때의 성능을 비교할 기준이 될 것입니다.
인덱스 없이 SQLite은 전체 테이블 스캔을 수행합니다. 즉, 테이블의 모든 행을 검사하여 일치하는 결과를 찾아야 합니다. 작은 데이터셋의 경우는 관리할 수 있지만, 레코드 수가 증가하면 검색에 걸리는 시간이 급격하게 증가합니다. 이를 확인하기 위해 기본적인 SELECT
쿼리를 실행하여 특정 학생의 이름으로 검색하고 수행 시간을 측정해 보겠습니다.
먼저, Students
테이블을 이름이 특정한 학생을 조회하는 쿼리를 실행합니다. Python의 time
모듈을 사용하여 쿼리 실행 시간을 기록하여 성능을 측정합니다.
import sqlite3
import time
def query_without_index(search_name):
"""Query the Students table by name without an index and measure the time taken."""
DB에 'with'를 사용하여 연결하기
with sqlite3.connect('my_database.db') as connection:
cursor = connection.cursor()
시작 시간 측정
start_time = time.perf_counter_ns()
이름으로 학생을 찾는 SELECT 쿼리 실행
cursor.execute('''
SELECT * FROM Students WHERE name = ?;
''', (search_name,))
모든 결과 가져오기 (실제로는 하나나 몇 개일 것)
results = cursor.fetchall()
종료 시간 측정
end_time = time.perf_counter_ns()
총 소요 시간 계산
elapsed_time = (end_time - start_time) / 1000
결과 및 소요 시간 표시
print(f"Query completed in {elapsed_time:.5f} microseconds.")
print("Results:", results)
예제: 이름으로 학생 검색
query_without_index('Ojasvi Dhawan')
다음은 출력입니다:
Query completed in 1578.10000 microseconds.
Results: [(104, 'Ojasvi Dhawan', 21, '[email protected]')]
위 스크립트를 실행하면, 인덱스 없이 `Students` 테이블을 검색하는 데 걸리는 시간을 볼 수 있습니다. 예를 들어, 테이블에 10,000개의 레코드가 있으면, 테이블의 크기와 하드웨어에 따라 1000-2000 마이크로초가 걸릴 수 있습니다. 작은 데이터셋의 경우는 너무 느릴 것 같지 않을 수 있지만, 레코드가 더 많아지면 성능이 떨어질 것입니다.
`time.perf_counter_ns()`를 사용하여 쿼리 실행에 소요된 시간을 나노초로 측정합니다. 이 방법은 작은 시간 간격의 벤치마킹에 매우 정확합니다. 읽기 쉽게 마이크로초(us
)로 변환합니다.
쿼리 계획 소개
SQLite에서 쿼리가 어떻게 실행되는지 이해하면 성능 瓶颈(bottleneck)을 식별하고 코드를 최적화 할 수 있습니다. SQLite는 이러한 작업을 도울 수 있는 도구를 제공합니다. 이 도구는 EXPLAIN QUERY PLAN
명령으로 쿼리의 실행 과정을 분석할 수 있습니다.
이 섹션에서는 EXPLAIN QUERY PLAN
명령을 어떻게 사용하여 쿼리의 내부 동작을 시각化하고 이해하는지를 소개할 것입니다. 특히, SQLite가 인덱스가 存在하지 않는 경우 전체 테이블 스캔(full table scan)를 수행하는 방법을 알아봅시다.
이제 EXPLAIN QUERY PLAN
를 사용하여 Students
테이블에 인덱스가 없는 상태下에 이름으로 학생을 찾기를 시도할 것입니다. 이름으로 일치하는 行을 찾기 위한 SQLite가 취할 수행 단계를 쿼리 계획(query plan)이 揭示할 것입니다.
import sqlite3
def explain_query(search_name):
"""Explain the query execution plan for a SELECT query without an index."""
with sqlite3.connect('my_database.db') as connection:
cursor = connection.cursor()
# EXPLAIN QUERY PLAN 사용하여 쿼리의 실행 방법 분석
cursor.execute('''
EXPLAIN QUERY PLAN
SELECT * FROM Students WHERE name = ?;
''', (search_name,))
# 쿼리 계획을 가져와 보여주기
query_plan = cursor.fetchall()
print("Query Plan:")
for step in query_plan:
print(step)
# 이름으로 search하는 쿼리 계획 분석 예
explain_query('Ojasvi Dhawan')
이 코드를 실행하면 SQLite는 쿼리를 실행하는 방법에 대한 구성 요소를 돌려 줄 것입니다. 아래는 output의 예입니다.
Query Plan:
(2, 0, 0, 'SCAN Students')
이는 SQLite가 Students
테이블을 전체(full table scan)로 스캔하여 name
열의 값이 제공된 값(Ojasvi Dhawan
)과 일치하는 行을 찾는 것을 나타냅니다. name
열에 인덱스가 없기 때문에 SQLite는 모든 行을 확인해야 합니다.
인덱스를 생성하는 방법
인덱스를 컬럼에 생성하는 것은 SQLite가 쿼리 operations시 行을 더 quickly찾을 수 있게 해줍니다. 전체 테이블을 스캔하는 대신, SQLite는 인덱스를 사용하여 직접 관련 行에 가는 것으로, 특히 대량의 데이터셋을 사용하는 것이 쿼리를 substantially acceleratesthat – especially those involving large datasets.
인덱스를 생성하기 위해서는 다음과 같은 SQL 명령어를 사용하십시오.
CREATE INDEX IF NOT EXISTS index-name ON table (column(s));
이 예에서는 Students
테이블의 name
列에 인덱스를 생성하는 것을 예시로 보겠습니다. 다음과 같이 Python을 사용하여 이를 하는 方法입니다.
import sqlite3
import time
def create_index():
"""Create an index on the name column of the Students table."""
with sqlite3.connect('my_database.db') as connection:
cursor = connection.cursor()
# SQL command to create an index on the name column
create_index_query = '''
CREATE INDEX IF NOT EXISTS idx_name ON Students (name);
'''
# Measure the start time
start_time = time.perf_counter_ns()
# Execute the SQL command to create the index
cursor.execute(create_index_query)
# Measure the start time
end_time = time.perf_counter_ns()
# Commit the changes
connection.commit()
print("Index on 'name' column created successfully!")
# Calculate the total time taken
elapsed_time = (end_time - start_time) / 1000
# Display the results and the time taken
print(f"Query completed in {elapsed_time:.5f} microseconds.")
# Call the function to create the index
create_index()
Output:
Index on 'name' column created successfully!
Query completed in 102768.60000 microseconds.
인덱스를 생성하는 것이 이렇게 오래 걸리는 것처럼 (102768.6 microseconds)하지만 이는 한 번의 operatioin입니다. 여러 쿼리를 실행할 때 substanatial speed-up을 얻을 수 있습니다. 다음 sectons에서는 다시 데이터베이스에 대해 쿼리를 실행하여 이 인덱스를 통한 성능 개선을 관찰할 것입니다.
인덱스를 사용하여 쿼리하는 방법
이 부분에서는 이전에 실행한 것처럼 SELECT
쿼리를 실행하ますが, 이번에는 Students
表의 name
열에 생성한 인덱스를 이용할 것입니다. 인덱스를 이용한 성능 향상을 관찰하기 위해 실행 시간을 測定하고 로그를 기록하겠습니다.
import sqlite3
import time
def query_with_index(student_name):
"""Query the Students table using an index on the name column."""
with sqlite3.connect('my_database.db') as connection:
cursor = connection.cursor()
# SQL 명령어로 이름으로 학생을 선택하기
select_query = 'SELECT * FROM Students WHERE name = ?;'
# 실행 시간을 測定하기
start_time = time.perf_counter_ns() # 타이머를 시작하기
# 제공된 학생 이름으로 쿼리를 실행하기
cursor.execute(select_query, (student_name,))
result = cursor.fetchall() # 모든 결과를 가져오기
end_time = time.perf_counter_ns() # 타이머를 끝내기
# 경과 시간을 微秒(microsecond)로 계산하기
execution_time = (end_time - start_time) / 1000
# 결과와 실행 시간을 표시하기
print(f"Query result: {result}")
print(f"Execution time with index: {execution_time:.5f} microseconds")
# 예: 이름으로 학생을 search하기
query_with_index('Ojasvi Dhawan')
이번에 얻는 출력은 다음과 같습니다:
Query result: [(104, 'Ojasvi Dhawan', 21, '[email protected]')]
Execution time with index: 390.70000 microseconds
인덱스를 사용하지 않은 것과 비교해서 실행 시간이 显著하게 줄어들었음을 관찰할 수 있습니다.
이제 Students
表의 name
열에 인덱스가 있는 쿼리의 실행 계획을 분석해봅시다. 同样의 스크립트를 다시 실행하여 쿼리를 설명하면 아래의 출력이 얻어지게 합니다:
Query Plan:
(3, 0, 0, 'SEARCH Students USING INDEX idx_name (name=?)')
계획이 이제 idx_name
인덱스를 사용하고 있으며, 스캔 해야 하는 行의 수를 значитель히 줄이는 것이 쿼리 실행의 빠른 처리를 导致하였음을 보여줍니다.
성능 결과 비교
이제 인덱스를 사용하고 그렇지 않고 쿼리를 수행할 때 얻은 성능 결과를 요약해보겠습니다.
수행 시간 비교
쿼리 유형 | 수행 시간 (마이크로초) |
인덱스 없음 | 1578.1 |
인덱스 있음 | 390.7 |
성능 개선 요약
-
인덱스가 있는 쿼리는 인덱스가 없는 쿼리보다 약 4.04 배 빠릅니다.
-
인덱스를 추가한 후 수행 시간이 약 75.24% 개선되었습니다.
인덱스 사용 최적 사례
인덱스는 SQLite 데이터베이스의 성능을大幅하게 향상시킬 수 있지만, 신중하게 사용해야 합니다. 인덱스로 작업할 때 고려해야 하는 몇 가지 최적 사례입니다:
인덱스를 사용할 때와 그 이유
-
자주 사용되는 쿼리 열:
SELECT
쿼리에서 자주 사용되는 열에 인덱스를 사용하십시오. 특히WHERE
,JOIN
,ORDER BY
절에서 사용되는 것들입니다. 이러한 열에 인덱스를 설정하면 쿼리 실행 시간을 크게 줄일 수 있기 때문입니다. -
유일성 제약: 유일한 값을 가질 수 있는 열(예: 사용자 이름이나 이메일 주소)가 있으면, 인덱스를 생성하여 이 제약을 효율적으로 强制할 수 있습니다.
-
大数据集: RECORD의 수가 많은 테이블에 대해, 인덱스는 점一滴 더 유용해집니다. 그들은 快速 조회를 可能하게 해줍니다, 이것은 자료가 增长的 과정에서 パフォーマン스를 유지하는 데 필요합니다.
-
複合索引: 여러 열에 대해 필터링 또는 정렬되는 쿼리에 대해 複合 인덱스를 생성하는 것을 고려하세요. 예를 들어
name
과age
両方에 대한 인덱스가 있다면, 이러한 쿼리의 optimization을 도울 수 있습니다.
인덱스의潛在적인 단점
인덱스는 显著的 이점을 제공하지만, 몇몇潛在적인 단점이 있습니다:
-
입력/업데이트 연산이 느림: 인덱스가 있는 테이블에 레코드를 입력하거나 업데이트할 때, SQLite은 인덱스도 업데이트해야 하므로 이러한 연산이 느릴 수 있습니다. 이는 각 입력이나 업데이트마다 인덱스 구조를 유지하기 위한 추가적인 오버헤드가 필요하기 때문입니다.
-
저장소 요구량 증가: 인덱스는 추가적인 디스크 공간을 차지합니다. 큰 테이블의 경우, 저장소 비용은 상당할 수 있습니다. 이를 데이터베이스 스키마를 디자인할 때 고려하시고, 특히 저장소 자원이 제한된 시스템에서는 더욱 그렇습니다.
-
複雑한 인덱스 관리: too many indexes can complicate database management. It may lead to situations where you have redundant indexes, which can degrade performance rather than enhance it. Regularly reviewing and optimizing your indexes is a good practice.
Indexes are powerful tools for optimizing database queries, but they require careful consideration. Striking a balance between improved read performance and the potential overhead on write operations is key. Here are some strategies for achieving this balance:
-
Query Performance 모니터링: SQLite의
EXPLAIN QUERY PLAN
을 사용하여 인덱스를 사용하고 사용하지 않는 것에 따라 쿼리의 성능을 분석하십시오. 이러한 인덱스의 중요성과 불필요성을 identifierify하는데 도움이 됩니다. -
정기적인 관리: 주기적으로 인덱스를 리뷰하고 이를 여전히 필요하다는 것을 확인하십시오. 중복되거나 거의 사용되지 않는 인덱스를 제거하여 데이터베이스 operatioin을 스트림라인 하십시오.
-
테스트 및 평가: 인덱스를 생산 환경에 实施하기 전에 透彻한 테스트를 실시하여 읽기 및 쓰기 操作에 대한 영향을 이해하십시오.
이러한 ベスト 实践를 따르면 인덱스의 이점을 利用할 수 있으며 가능한 drawback을 최소화하여 SQLite 데이터베이스의 パフォーマンス와 効率를 改善시킬 수 있습니다.
이 sectioin에서는 Python을 사용하여 SQLite로 작업하는 과정에서 에러와 예외를 처리하는 方法을 讨議할 것입니다. 적절한 에러 처리는 데이터베이스의 정신성을 보장하고 응용 프로그램이 예측 가능하게 행동하는 것이 중요합니다.
-
제약조건 위반: 이는 데이터를 挿入하거나 수정하는 것에 대해 데이터베이스 제약조건을 위반하는지 여부를 추론하는 것이며, 예를 들어 중복된 기본키를 삽입하는 것은 에러를 유발합니다.
-
형식 불일치: 잘못된 형식의 데이터(例如, 숫자가 期待され는 곳에 문자열을 삽입하는 것)를 삽입하는 것은 에러로 나타낼 수 있습니다.
-
DB 잠금 에러: 다른 프로세스 또는 연결이 数据库을 쓴 状態에서 그 에러를 일으킵니다.
-
문법 에러: SQL 문법에 에러가 있으면 명령어를 실행하려고 하는 때 에러가 발생합니다.
Python의 Exception Handling을 사용하는 方法
Python의 내장 예외 처리 mechanisims(try
와 except
)은 SQLite 操作用에서 에러를 관리하는 데 필수적이며, 이러한 구조를 사용하면 프로그램이 Down되지 않고 예외를 catch하고 적절하게 응답할 수 있습니다.
다음은 데이터베이스에 데이터를 삽입할 때 에러를 처리하는 기본적인 예시입니다:
import sqlite3
def add_customer_with_error_handling(name, balance):
"""Add a new customer with error handling."""
try:
with sqlite3.connect('my_database.db') as connection:
cursor = connection.cursor()
cursor.execute(
"INSERT INTO Customers (name, balance) VALUES (?, ?);", (name, balance))
connection.commit()
print(f"Added customer: {name} with balance: {balance}")
except sqlite3.IntegrityError as e:
print(f"Error: Integrity constraint violated - {e}")
except sqlite3.OperationalError as e:
print(f"Error: Operational issue - {e}")
except Exception as e:
print(f"An unexpected error occurred: {e}")
# 사용 예시
add_customer_with_error_handling('Vishakha', 100.0) # 유효한 값
add_customer_with_error_handling('Vishakha', 150.0) # 중복 입력
이 예시에서:
-
我们 catch
IntegrityError
, 유니크 제약조건을 위반하여 발생하는 것들의 위반을 捉えます. -
我们 catch
OperationalError
일반적인 데이터베이스 관련 문제(예: 데이터베이스가 잠겨 있는 에러)에 대한 에러를 捉えます. -
또한 일반적인
except
区块을 가지고 예상치 못한 예외를 처리할 수 있습니다.
Output:
Added customer: Vishakha with balance: 100.0
Error: Integrity constraint violated - UNIQUE constraint failed: Customers.name
데이터베이스 정합성을 보장하기 위한 ベスト 프ACTICES
-
트랜잭션 사용: 여러 관련 작업을 수행할 때 항상 트랜잭션을 사용하십시오 (이전 섹션에서 설명한 대로). 이를 통해 모든 작업이 성공하거나 모두 실패하도록 보장하여 일관성을 유지할 수 있습니다.
-
입력 데이터 유효성 검사: SQL 명령을 실행하기 전에 입력 데이터의 유효성을 검사하여 예상 기준을 충족하는지 확인하십시오 (예: 올바른 유형, 허용 범위 내).
-
특정 예외 처리: 항상 특정 예외를 처리하여 다른 유형의 오류를 적절히 처리하십시오. 이렇게 하면 더 명확한 오류 처리와 디버깅이 가능해집니다.
-
오류 로깅: 콘솔에 오류를 출력하는 대신 파일이나 모니터링 시스템에 로그를 남기는 것을 고려하십시오. 이렇게 하면 프로덕션에서 문제를 추적하는 데 도움이 됩니다.
-
우아한 강등: 애플리케이션이 오류를 우아하게 처리하도록 설계하세요. 작업이 실패할 경우 애플리케이션이 충돌하지 않고 사용자에게 의미 있는 피드백을 제공하세요.
-
데이터 정기 백업: 중요한 오류나 손상이 발생할 경우 데이터 손실을 방지하기 위해 데이터베이스를 정기적으로 백업하세요.
-
준비된 문장 사용: 준비된 문장은 SQL 삽입 공격을 방지하고 반복된 쿼리에 대해 더 나은 성능을 제공할 수 있습니다.
데이터 내보내기 및 가져오기 방법 [보너스 섹션]
이 섹션에서는 SQLite 데이터베이스에서 CSV 및 JSON과 같은 일반 형식으로 데이터를 내보내고, Python을 사용하여 이러한 형식에서 SQLite로 데이터를 가져오는 방법을 배웁니다. 이는 데이터 공유, 백업 및 다른 애플리케이션과의 통합에 유용합니다.
SQLite에서 CSV로 데이터 내보내기
Python의 내장 라이브러리를 사용하면 CSV(Comma-Separated Values) 파일로 데이터를 내보내는 것이 간단합니다. CSV 파일은 데이터 저장 및 교환에 널리 사용되므로 데이터 내보내기에 편리한 형식입니다.
SQLite 表에서 CSV 파일로 데이터 導出하는 方法:
import sqlite3
import csv
def export_to_csv(file_name):
"""Export data from the Customers table to a CSV file."""
with sqlite3.connect('my_database.db') as connection:
cursor = connection.cursor()
# 모든 고객 데이터를 가져오기 위한 쿼리 실행
cursor.execute("SELECT * FROM Customers;")
customers = cursor.fetchall()
# 데이터를 CSV에 적기
with open(file_name, 'w', newline='') as csv_file:
csv_writer = csv.writer(csv_file)
csv_writer.writerow(['ID', 'Name', 'Balance']) # 헤더 쓰기
csv_writer.writerows(customers) # 데이터 行 쓰기
print(f"Data exported successfully to {file_name}.")
# 예시 사용
export_to_csv('customers.csv')
JSON으로 데이터 導出하는 方法
대신, JSON (JavaScript Object Notation) 파일로 데이터를 導出할 수 있으며, 이는 데이터 교환에 특ial적으로 웹 应用程序에서 인기있는 형식입니다.
JSON으로 데이터 導出하는 예시가 다음과 같습니다:
import json
import sqlite3
def export_to_json(file_name):
"""Export data from the Customers table to a JSON file."""
with sqlite3.connect('my_database.db') as connection:
cursor = connection.cursor()
# 모든 고객 데이터를 가져오기 위한 쿼리 실행
cursor.execute("SELECT * FROM Customers;")
customers = cursor.fetchall()
# 데이터를 딕셔너리의 목록으로 변환
customers_list = [{'ID': customer[0], 'Name': customer[1],
'Balance': customer[2]} for customer in customers]
# 데이터를 JSON에 적기
with open(file_name, 'w') as json_file:
json.dump(customers_list, json_file, indent=4)
print(f"Data exported successfully to {file_name}.")
# 예시 사용
export_to_json('customers.json')
CSV에서 SQLite로 데이터 導入하는 方法
CSV 파일을 SQLite 데이터베이스로 이mport하는 것도 가능합니다. 이는 이미 존재하는 dataset로 데이터베이스를 populte하는 것이 유용합니다.
CSV 파일から 데이터를 導入하는 方法은 다음과 같습니다:
import csv
import sqlite3
def import_from_csv(file_name):
"""Import data from a CSV file into the Customers table."""
with sqlite3.connect('my_database.db') as connection:
cursor = connection.cursor()
# CSV 파일을 읽기 위해 엽니다
with open(file_name, 'r') as csv_file:
csv_reader = csv.reader(csv_file)
next(csv_reader) # 헤더 행을 건너뜁니다
# 각 행을 Customers 테이블에 삽입합니다
for row in csv_reader:
cursor.execute(
"INSERT INTO Customers (name, balance) VALUES (?, ?);", (row[1], row[2]))
connection.commit()
print(f"Data imported successfully from {file_name}.")
# 사용 예시
import_from_csv('customer_data.csv')
JSON에서 SQLite로 데이터 가져오는 방법
유사하게, JSON 파일에서 데이터를 가져오는 것도 간단합니다. JSON 파일을 읽고 데이터를 SQLite 테이블에 삽입할 수 있습니.
다음은 그 방법입니다:
import json
import sqlite3
def import_from_json(file_name):
"""Import data from a JSON file into the Customers table."""
with sqlite3.connect('my_database.db') as connection:
cursor = connection.cursor()
# JSON 파일을 읽기 위해 엽니다
with open(file_name, 'r') as json_file:
customers_list = json.load(json_file)
# 각 고객을 Customers 테이블에 삽입합니다
for customer in customers_list:
cursor.execute("INSERT INTO Customers (name, balance) VALUES (?, ?);", (customer['Name'], customer['Balance']))
connection.commit()
print(f"Data imported successfully from {file_name}.")
# 사용 예시
import_from_json('customer_data.json')
마무리
이제 마무리입니다! 이 가이드에서는 SQLite와 Python을 사용하여 환경 설정에서부터 데이터 쿼리 및 조작, 정보 내보내기 및 가져오기까지의 기본 사항을 소개했습니다. 도움이 되었기를 바라며, SQLite를 사용한 프로젝트에 대한 관심을 불러일으켰기를 바랍니다.
이제 새로 얻은 지식을 실전에서 활용할 시간입니다! SQLite와 Python을 사용하여 프로젝트를 만들어 보세요. 도서관 관리, 예산 도구, 또는 독창적인 무언가를 위한 간단한 응용 프로그램 등 가능성은 무궁무진합니다.
프로젝트를 완료한 후 Twitter에 공유하고 저를 태그하세요! 여러분이 만든 것을 보고 여러분의 성취를 축하하고 싶습니다.
이 튜토리얼의 모든 코드는 GitHub에서 찾을 수 있습니다. 따라가 주셔서 감사드리며, 코딩에 즐거움을 느껴보세요!
freeCodeCamp 기사에 대한 목차를 무료로 생성하려면 TOC 생성기 도구를 사용하세요.
Source:
https://www.freecodecamp.org/news/work-with-sqlite-in-python-handbook/