SQLite является одним из наиболее популярных систем управления реляционной базой данных (RDBMS). Она является легким в использовании, что意味着, что она не занимает много места на вашем компьютере. Одна из лучших ее особенностей в том, что она безсерверная, так что вам не нужно устанавливать или управлять отдельным сервером, чтобы использовать ее.
Вместо этого, все сохраняется в простом файле на вашем компьютере. Также она требует нуля настроек, так что нет никакого сложного процесса установки, что делает ее идеальной для новичков и небольших проектов.
SQLite – отличный выбор для небольших и средних приложений, поскольку она легка в использовании, быстра, и может выполнять большинство задач, которые могут выполнять более крупные базы данных, но без труда управления дополнительным программным обеспечением. Независимо от того, whether you’re building a personal project or prototyping a new app, SQLite is a solid option to get things up and running quickly.
In this tutorial, you’ll learn how to work with SQLite using Python. Here’s what we’re going to cover in this tutorial:
-
Как оптимизировать производительность запросов SQLite с помощью индексирования
-
Как экспортировать и импортировать данные [дополнительный раздел]
Этот учебник идеально подходит для людей, которые хотят начать работать с базами данных, не занимаясь сложными настройками.
Как настроить ваш Python-окружение
До работы с SQLite нам надо убедиться, что ваше Python-окружение готово. Вот как настроить все.
Установка Python
Если Python еще не установлен на вашем компьютере, вы можете скачать его с официального веб-сайта Python. Следуйте инструкциям установки для вашей операционной системы (Windows, macOS или Linux).
Чтобы проверить, установлен ли Python, откройте терминал (или командную строку) и введите:
python --version
Это должно показать текущую установленную версию Python. Если она не установлена, следуйте инструкциям с Python-сайта.
Установка модуля SQLite3
Добрая новость заключается в том, что SQLite3 включен в Python по умолчанию! Вам не нужно его отдельно устанавливать, так как он включен в стандартную библиотеку Python. Это意味着 вы можете начать использовать его сразу, без дополнительной настройки.
Как создать виртуальную среду (необязательно, но рекомендуемо)
Хорошим решением является создание для каждого проекта виртуальной среды, чтобы сохранять ваши зависимости в порядке. Виртуальная среда подобна чистому листу, где вы можете устанавливать пакеты без влияния на глобальную установку Python.
Чтобы создать виртуальную среду, следуйте этим шагам:
-
Сначала откройте терминал или командную строку и перейдите в директорию, где вы хотите создать ваш проект.
-
Введите следующую команду, чтобы создать виртуальную среду:
python -m venv env
В этом месте env
является именем виртуальной среды. Вы можете назвать ее любым своим именем.
- Активируйте виртуальную среду:
# Используйте команду для Windows
env\Scripts\activate
# Используйте команду для macOS/Linux:
env/bin/activate
После активации виртуальной среды, вы заметите, что на вашем терминале изменилась оболочка, показывая имя виртуальной среды. Это значит, что теперь вы работаете внутри нее.
Установка необходимых библиотек
Для этого проекта нам понадобится несколько дополнительных библиотек. В частности, мы будем использовать:
-
pandas
: Это дополнительная библиотека для обработки и отображения данных в табличном формате, полезная для продвинутых случаев использования. -
faker
: Эта библиотека поможет нам генерировать поддельные данные, например, случайные имена и адреса, которые мы можем вставить в нашу базу данных для тестирования.
Чтобы установить pandas
и faker
, просто выполните следующие команды:
pip install pandas faker
Это установит pandas
и faker
в ваше виртуальное окружение. После этого ваша среда настроена, и вы готовы приступить к созданию и управлению базой данных SQLite на Python!
Как создать базу данных SQLite
База данных – это структурированный способ хранения и управления данными, чтобы к ним можно было легко получить доступ, обновить и организовать. Это как цифровая картотека, которая позволяет эффективно хранить большие объемы данных, будь то простое приложение или более сложная система. Для организации данных в базах данных используются таблицы, в которых строки и столбцы представляют отдельные записи и их атрибуты.
Как работают базы данных SQLite
В отличие от большинства других систем баз данных, SQLite является безсерверной базой данных. Это意味着 она не требует установки или управления сервером, что делает её легкой и удобной для использования. Все данные сохраняются в единственном файле на вашем компьтере, который вы можете легко перемещать, share, или back up. хотя она простая, SQLite достаточно мощна, чтобы выполнять многие общие задачи баз данных и широко используется в мобильных приложениях, встроенных системах и проектах среднего размера.
Как создать новую базу данных SQLite
Давайте создадим новую базу данных SQLite и узнаем, как работать с ней с помощью библиотеки Python sqlite3
.
Соединение с базой данных
Так как sqlite3
уже установлен, вам нужно просто импортировать ее в вашем скрипте Python. Чтобы создать новую базу данных или подключиться к существующей, мы используем метод 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()
.
Вот как вы можете использовать оператор with
для обработки соединений с базой данных:
import sqlite3
# Шаг 1: Используйте 'with' для подключения к базе данных (или создания новой) и автоматического закрытия после завершения
with sqlite3.connect('my_database.db') as connection:
# Шаг 2: Создайте объект курсора для взаимодействия с базой данных
cursor = connection.cursor()
print("Database created and connected successfully!")
# Не нужно вызывать connection.close(); это делается автоматически!
С этого момента мы будем использовать оператор with
в наших предстоящих примерах кода для эффективного управления подключениями к базе данных. Это сделает код более лаконичным и проще в поддержке.
Как создавать таблицы базы данных
Теперь, когда мы создали базу данных SQLite и подключились к ней, следующим шагом является создание таблиц внутри базы данных. Таблица – это место, где мы будем хранить наши данные, организованные в строки (записи) и столбцы (атрибуты). Для этого примера мы создадим таблицу под названием Students
, чтобы хранить информацию о студентах, которую мы будем использовать в последующих разделах.
Чтобы создать таблицу, мы используем оператор SQL CREATE TABLE
. Эта команда определяет структуру таблицы, включая имена столбцов и типы данных для каждого столбца.
Вот простая команда SQL для создания таблицы Students
с следующими полями:
-
id
: Уникальный идентификатор для каждого студента (целое число). -
name: Имя студента (текст).
-
age: Возраст студента (целое число).
-
email: Электронная почта студента (текст).
Команда SQL для создания этой таблицы будет выглядеть следующим образом:
CREATE TABLE Students (
id INTEGER PRIMARY KEY AUTOINCREMENT,
name TEXT NOT NULL,
age INTEGER,
email TEXT
);
Мы можем выполнить SQL команду CREATE TABLE
в Python с использованием библиотеки sqlite3
.みなさんと一緒にその方法を見ていきましょう。
import sqlite3
# Используем 'with', чтобы соединиться с SQLite-базой данных и автоматически закрыть соединение, когда она будет выполнена
with sqlite3.connect('my_database.db') as connection:
# Создаем объект курсора
cursor = connection.cursor()
# Запишем SQL-команду для создания таблицы Students
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()
: Это сохраняет (подтверждает) изменения в базе данных.
Когда вы будете запускать Python-код выше, он создаст таблицу Students
в файле базы данных my_database.db
. Вы также увидите сообщение в терминале, подтверждающее успешное создание таблицы.
Если вы используете Visual Studio Code, вы можете установить расширение SQLite Viewer для просмотра баз данных SQLite.
Типы данных в SQLite и их отображение на Python
SQLite поддерживает несколько типов данных, которые нам необходимо понимать при определении наших таблиц. Вот краткий обзор распространенных типов данных SQLite и их соответствия типам Python:
Тип данных SQLite | Описание | Эквивалент Python |
INTEGER | Целые числа | int |
TEXT | Текстовые строки | str |
REAL | Floating-точечные числа | float |
BLOB | Двоичные данные (например.g., изображения, файлы) | bytes |
NULL | Представляет собой отсутствие значения или недостающие данные | None |
В нашей таблице Students
:
-
id
имеет типINTEGER
, который соответствуетint
в Python. -
name
иemail
имеют типTEXT
, который отображается на Python’sstr
. -
age
также имеет типINTEGER
, соответствующий типуint
в Python.
Как вставить данные в таблицу
Теперь, когда у нас есть созданная таблица Students
, пришло время начать вставлять данные в базу данных. В этом разделе мы рассмотрим, как вставить как одну, так и несколько записей, используя Python и SQLite, а также как избежать распространенных проблем безопасности, таких как SQL-инъекции, с помощью параметризованных запросов.
Как вставить одну запись
Для вставки данных в базу данных мы используем команду SQL INSERT INTO
. Давайте начнем с вставки одной записи в нашу таблицу Students
.
Вот основный синтаксис SQL для вставки одной записи:
INSERT INTO Students (name, age, email)
VALUES ('John Doe', 20, '[email protected]');
Однако, вместо написания SQL-запроса непосредственно в нашем скрипте Python с зафиксированными значениями, мы будем использовать параметризованные запросы, чтобы сделать наш код более безопасным и гибким. Параметризованные запросы помогают предотвратить SQL-инъекции, распространенную атаку, при которой злоумышленники могут манипулировать SQL-запросом, передавая вредоносные данные.
Вот как мы можем вставить одну запись в таблицу Students
, используя параметризованный запрос:
import sqlite3
# Используйте 'with' для автоматического открытия и закрытия соединения
with sqlite3.connect('my_database.db') as connection:
cursor = connection.cursor()
# Вставляем запись в таблицу Students
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!")
Запятые ?
представляют собой значения, которые будут вставлены в таблицу. Real values are passed as a tuple (student_data
) in the cursor.execute()
method.
Как вставить несколько записей
Если вы хотите вставить несколько записей одновременно, вы можете использовать метод executemany()
в Python. Этот метод принимает список кортежей, где каждый кортеж представляет одну запись.
Чтобы наш пример стал более динамичным, мы можем использовать библиотеку Faker
для генерации случайных данных о студентах. Это полезно для тестирования и имитации реальных сценариев.
from faker import Faker
import sqlite3
# Инициализируем Faker
fake = Faker(['en_IN'])
# Используйте 'with' для автоматического открытия и закрытия соединения
with sqlite3.connect('my_database.db') as connection:
cursor = connection.cursor()
# Вставляем запись в таблицу Students
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()
# Выводим сообщение о подтверждении
print("Fake student records inserted successfully!")
В этом коде:
-
Faker()
генерирует случайные имена, возраст и электронные адреса студентов.Передача локали ([‘en_IN’]
) является опциональной. -
cursor.executemany()
: Этот метод позволяет нам вставлять несколько записей одновременно, что делает код более эффективным. -
students_data
: Список кортежей, где каждый кортеж представляет данные одного студента.
Как обращаться с общими проблемами: SQL Инъекция
SQL инъекция – это уязвимость в безопасности, когда атакующие могут вставлять или изменять SQL запросы, предоставляя вредные входные данные. Например, атакующий может попытаться вставить код, такой как '; DROP TABLE Students; --
, чтобы удалить таблицу.
Используя параметризированные запросы (как показано выше), мы избегаем этой проблемы. Placeholders ?
в параметризированных запросах убеждают значения входных данных рассматриваться как данные, а не как часть SQL команды. Это делает выполнение вредоносного кода невозможным.
Как выполнять запросы к данным
Теперь, когда мы вставили какое-то данное в нашу таблицу Студенты
, пора узнать, как можно извлечь данные из таблицы. Мы рассмотрим различные методы для извлечения данных в Python, включая fetchone()
, fetchall()
и fetchmany()
.
Чтобы выполнить запрос данных из таблицы, мы используем запрос SQL SELECT
. Вот пример simple SQL команды, чтобы выбрать все столбцы из таблицы Студенты
:
SELECT * FROM Students;
Эта команда извлекает все записи и столбцы из таблицы Студенты
. Мы можем выполнить этот запрос SELECT
в Python и извлечь результаты.
Как извлечь все записи
Вот, как мы можем извлечь все записи из таблицы Студенты
:
import sqlite3
# Используем 'with' для подключения к SQLite-базе данных
with sqlite3.connect('my_database.db') as connection:
# Создаем объект курсора
cursor = connection.cursor()
# Записываем 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]')
Как извлечь одну запись
Если вы хотите извлечь только одну запись, вы можете использовать метод fetchone()
:
import sqlite3
# Использование 'with' для подключения к SQLite базе данных
with sqlite3.connect('my_database.db') as connection:
# Создание объекта курсора
cursor = connection.cursor()
# Запись SQL команды для выбора всех записей из таблицы Students
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
# Использование 'with' для подключения к SQLite базе данных
with sqlite3.connect('my_database.db') as connection:
# Создание объекта курсора
cursor = connection.cursor()
# Запись SQL команды для выбора всех записей из таблицы Students
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
из результатов запроса. Это делает меняние и визуализацию данных более удобной.
Вот как можно получить все записи и отобразить их как DataFrame pandas:
import sqlite3
import pandas as pd
# Использование 'with' для подключения к SQLite-базе данных
with sqlite3.connect('my_database.db') as connection:
# Запишите SQL-запрос для выбора всех записей из таблицы Students
select_query = "SELECT * FROM Students;"
# Используйте pandas, чтобы прочитать SQL-запрос непосредственно в DataFrame
df = pd.read_sql_query(select_query, connection)
# Отобразите DataFrame
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-запрос и возвращает результаты в качестве DataFrame pandas.
Как обновить и удалить данные
В этом разделе мы leaned, как обновить существующие записи и удалить записи из нашей Students
таблицы, используя SQL-запросы в Python. Это необходимо для управления и сохранения ваших данных эффективно.
Обновление существующих записей
Чтобы изменить существующие записи в базе данных, мы используем 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'
# Execute the SQL command with the data
cursor.execute(update_query, (new_age, student_name))
# Отправить изменения для сохранения обновления
connection.commit()
# Print a confirmation message
print(f"Updated age for {student_name} to {new_age}.")
В этом примере мы использовали параметризированные запросы для предотвращения SQL injection.
Как удалять записи из таблицы
Для удаления записей из базы данных мы используем SQL запрос DELETE
. Эта команда позволяет удалить одну или более строк на основании определенного условия.
Например, если мы хотим удалить студента с именем ‘Jane Doe’, SQL команда выглядела бы так:
DELETE FROM Students
WHERE name = 'Jane Doe';
Давайте напишем Python код для удаления конкретного студента из нашей таблицы Students
с использованием with
заявления.
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'
# Execute the SQL command with the data
cursor.execute(delete_query, (student_name,))
# Отправить изменения для сохранения удаления
connection.commit()
# Print a confirmation message
print(f"Deleted student record for {student_name}.")
важные подумать о позиции
-
Условия: Всегда используйте оператор
WHERE
при обновлении или удалении записей, чтобы избежать изменения или удаления всех строк в таблице. Без оператораWHERE
команда затрагивает каждую строку в таблице. -
Резервное копирование: Хорошей практикой является создание резервной копии базы данных перед выполнением обновлений или удалений, особенно в производственных средах.
Как использовать транзакции
Транзакция – это последовательность одной или нескольких операций SQL, которые рассматриваются как единое рабочее действие. В контексте базы данных транзакция позволяет выполнять несколько операций, которые либо все успешно завершатся, либо не будут выполнены вообще. Это обеспечивает консистентное состояние базы данных, даже в случае ошибок или непредвиденных проблем.
Например, если вы переводите деньги между двумя банковскими счетами, вы хотели бы, чтобы и дебет с одного счета, и кредит на другой счет произошли успешно или не были выполнены вообще. Если одна операция не удалась, другая не должна быть выполнена, чтобы поддерживать консистентность.
Зачем использовать транзакции?
-
Атомичность: Транзакции обеспечивают так называемый принцип атомичности, согласно которому серия операций выполняется как единое целое. Если одна из операций завершается неудачей, то все операции, совершенные в рамках транзакции, не будут осуществлены в базе данных.
-
Согласованность: Транзакции помогают поддерживать целостность базы данных, обеспечивая соблюдение всех правил и ограничений.
-
Изоляция: Каждая транзакция выполняется независимо от других, что предотвращает нежелательное взаимодействие между ними.
-
Сохранность: После того как транзакция завершена, изменения становятся永久的ными, даже в случае сбоя системы.
Когда использовать транзакции?
Транзакции следует использовать в следующих случаях:
-
Выполнение нескольких связанных операций, которые должны выполняться вместе или не выполняться вообще.
-
Изменение критических данных, которые требуют сохранения целостности и независимости.
-
Работа с операциями, которые могут потенциально потерпеть неудачу, такими как финансовые операции или миграции данных.
Как управлять транзакциями в Python
В SQLite транзакции управляются с помощью команд BEGIN
, COMMIT
и ROLLBACK
. Однако, при использовании модуля sqlite3
в Python, транзакции обычно управляются через объект соединения.
Запуск транзакции
Транзакция начинается имплицитно при выполнении любого SQL-запроса. Чтобы выполнить транзакцию эксплицитно, можно использовать команду BEGIN
:
cursor.execute("BEGIN;")
Однако, как правило, нет необходимости выполнять транзакцию вручную, так как SQLite автоматически начинает транзакцию при выполнении SQL-запроса.
Как привязать транзакцию
Чтобы сохранить все изменения, сделанные во время транзакции, используется метод commit()
. Это делает все изменения постоянными в базе данных.
connection.commit()
Мы уже использовали метод commit()
в приведенных выше примерах.
Откат транзакции
Если что-то идёт неправильно и вы хотите отменить изменения, сделанные во время транзакции, можете использовать метод rollback()
. Это отменит все изменения, сделанные с момента начала транзакции.
connection.rollback()
Пример использования транзакций в Python
Для иллюстрации использования транзакций в реальном мире сценарий, мы создадим новую таблицу под названием Customers
, чтобы управлять учетными записями клиентов. В этом примере мы предположим, что каждый клиент имеет balance
. Мы добавим двух клиентов в эту таблицу и выполним операцию перечисления средств между ними.
Первым делом, создадим Customers
таблицу и добавим двух клиентов:
import sqlite3
# Create the Customers table and add two customers
with sqlite3.connect('my_database.db') as connection:
cursor = connection.cursor()
# Create Customers table
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)
# Insert two customers
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:
import sqlite3
def transfer_funds(from_customer, to_customer, amount):
with sqlite3.connect('my_database.db') as connection:
cursor = connection.cursor()
try:
# Start a transaction
cursor.execute("BEGIN;")
# Deduct amount from the sender
cursor.execute(
"UPDATE Customers SET balance = balance - ? WHERE name = ?;", (amount, from_customer))
# Add amount to the receiver
cursor.execute(
"UPDATE Customers SET balance = balance + ? WHERE name = ?;", (amount, to_customer))
# Commit the changes
connection.commit()
print(
f"Transferred {amount} from {from_customer} to {to_customer}.")
except Exception as e:
# If an error occurs, rollback the transaction
connection.rollback()
print(f"Transaction failed: {e}")
# Example usage
transfer_funds('Ashutosh', 'Krishna', 80.0)
В этом примере сначала мы создали таблицу Customers
и вставили двух клиентов, Ashutosh с балансом ₹100 и Krishna с балансом ₹50. Затем мы осуществили перевод ₹80 от Ashutosh к Krishna. Используя транзакции, мы обеспечиваем, что как зачисление средств с счета Ashutosh, так и зачисление на счет Krishna выполняются как одна атомарная операция, сохраняя целостность данных в случае любых ошибок. Если перевод не удается (например, из-за недостаточности средств), транзакция откатится, и оба счета останутся неизменными.
Как оптимизировать производительность запросов SQLite с помощью индексации
Индексация является мощным методом, используемым в базах данных для улучшения производительности запросов. Индекс по сути является структурой данных, которая хранит расположение строк на основе определенных значений столбцов, так же как индекс в конце книги помогает быстро находить тему.
Без индекса SQLite должен сканировать всю таблицу строка за строкой, чтобы найти соответствующие данные, что становится неэффективным с ростом набора данных. Используя индекс, SQLite может непосредственно перейти к строкам, которые вам нужны, значительно ускорив выполнение запроса.
Как заполнить базу данных фейковыми данными
Чтобы эффективно проверить влияние индексации, нам нужен значительный набор данных. Вместо того, чтобы добавлять записи вручную, мы можем использовать библиотеку faker
, чтобы быстро генерировать фейковые данные. В этом разделе мы генерируем 10 000 фейковых записей и вставляем их в нашу таблицу Students
. Это будет моделировать реальную ситуацию, в которой база данных становится большой, и производительность запроса становится важной.
Мы будем использовать метод 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.")
# Вставляем 10,000 искусственных записей в таблицу Students
insert_fake_students(10000)
При запуске скрипта будут добавлены 10,000 искусственных записей о студентах в таблицу Students
. В следующей секции мы будем опрашивать базу данных и сравнивать производительность запросов с и без индексирования.
Как выполнять запросы без индексов
В этой секции мы будем опрашивать таблицу Students
без каких-либо индексов, чтобы наблюдать, как SQLite работает, когда отсутствуют какие-либо оптимизации. Это будет служить базой для сравнения производительности, когда мы позже добавим индексы.
Без индексов SQLite выполняет полный просмотр таблицы, что意味着 он должен проверить каждую строку в таблице, чтобы найти соответствующие результаты. Для небольших наборов данных это допустимо, но с ростом числа записей время поиска резко увеличивается.Let’s see this in action by running a basic SELECT
query to search for a specific student by name and measure how long it takes.
First, we’ll query the Students
table by looking for a student with a specific name. We’ll log the time taken to execute the query using Python’s time
module to measure the performance.
import sqlite3
import time
def query_without_index(search_name):
"""Query the Students table by name without an index and measure the time taken."""
# Подключение к базе данных с использованием '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()
# Calculate the total time taken
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
) для большей readability.
ВводятQuery Plan
Когда работаешь с базами данных, понимание того, как выполняются запросы, помогает обнаружить performance bottlenecks и оптимизировать твой код. SQLite предоставляет полезный инструмент для этого, называемый EXPLAIN QUERY PLAN
, который позволяет анализировать шаги, которые SQLite делает для извлечения данных.
В этом разделе мы познакомимся с тем, как использовать EXPLAIN QUERY PLAN
, чтобы визуально представить и понять внутренние механизмы запроса — специфически, как SQLite выполняет полный просмотр таблицы, когда индекс отсутствует.
Давайте используем EXPLAIN QUERY PLAN
, чтобы увидеть, как SQLite извлекает данные из таблицы Students
без каких-либо индексов. Мы будем искать студента по имени, и плану запроса будет揭示 шаги, которые SQLite делает, чтобы найти соответствующие строки.
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)
# Пример: Анализ плана запроса для поиска по имени
explain_query('Ojasvi Dhawan')
Когда вы запустите этот код, SQLite вернет разбиение того, как он планирует выполнять запрос. Вот пример того, как выход может выглядеть:
Query Plan:
(2, 0, 0, 'SCAN Students')
Это указывает, что SQLite идет по всей таблице Students
(полный просмотр таблицы), чтобы найти строки, в которых столбец name
соответствует указанному значению (Ojasvi Dhawan
). TAKING INTO account, что никакого индекса на столбце name
не существует, SQLite должен просмотреть каждую строку в таблице.
Как создавать индекс
Создание индекса на столбце позволяет SQLite быстрее находить строки во время операций запроса. Вместо того, чтобы просматривать всю таблицу, SQLite может использовать индекс, чтобы немедленно перейти к соответствующим строкам, что значительно ускоряет запросы, особенно те, которые включают большие наборы данных.
Для создания индекса используется следующий SQL-команда:
CREATE INDEX IF NOT EXISTS index-name ON table (column(s));
В этом примере мы создадим индекс на столбце name
таблицы Students
. Вот как это можно сделать с помощью 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 команда для создания индекса на столбце name
create_index_query = '''
CREATE INDEX IF NOT EXISTS idx_name ON Students (name);
'''
# Измеряется начальное время
start_time = time.perf_counter_ns()
# Выполняется SQL-команда для создания индекса
cursor.execute(create_index_query)
# Измеряется начальное время
end_time = time.perf_counter_ns()
# Внесение изменений
connection.commit()
print("Index on 'name' column created successfully!")
# расчет общего времени
elapsed_time = (end_time - start_time) / 1000
# Отображение результатов и затраченного времени
print(f"Query completed in {elapsed_time:.5f} microseconds.")
# вызов функции для создания индекса
create_index()
Вывод:
Index on 'name' column created successfully!
Query completed in 102768.60000 microseconds.
虽然创建索引需要这么长时间(102768.6 микросекунд),但这是一次性操作。当运行多个查询时,您仍然会获得相当大的速度提升。在接下来的部分,我们将再次查询数据库,以观察此索引所实现的性能改进。
Как выполнять запросы с использованием индексов
В этом разделе мы выполним тот же запрос SELECT
, который был выполнен ранее, но на этот раз мы воспользуемся индексом, созданным на колонке name
таблицы Students
. Мы измерим и запишем время выполнения, чтобы наблюдать улучшения производительности, обеспечиваемые индексом.
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() # Останавливаем таймер
# Calculate the elapsed time in microseconds
execution_time = (end_time - start_time) / 1000
# Отображаем результаты и время выполнения
print(f"Query result: {result}")
print(f"Execution time with index: {execution_time:.5f} microseconds")
# Пример: поиск студента по имени
query_with_index('Ojasvi Dhawan')
В выходных данных мы получаем следующее:
Query result: [(104, 'Ojasvi Dhawan', 21, '[email protected]')]
Execution time with index: 390.70000 microseconds
Мы можем наблюдать значительное уменьшение времени выполнения по сравнению с тем, когда запрос выполнялся без индекса.
Посмотрим на план выполнения запроса для запроса с индексом на колонке name
таблицы Students
. Если вы выполните тот же скрипт снова, чтобы объяснить запрос, вы получите следующий вывод:
Query Plan:
(3, 0, 0, 'SEARCH Students USING INDEX idx_name (name=?)')
Теперь план показывает, что запрос использует индекс idx_name
, значительно уменьшая количество строк, которые нужно просканировать, что приводит к более быстрому выполнению запроса.
Сравнение результатов по performance
Теперь let’s обзор performance результатов мы получили при querying с и без индексы.
Сравнение времени выполнения
Тип запроса | Время выполнения (микросекунды) |
Без индекса | 1578,1 |
С индекса | 390,7 |
Résumé улучшения производительности
-
The запрос с индексом примерно 4,04 раза быстрее, чем запрос без индекса.
-
Время выполнения улучшилось приблизительно на 75,24% после добавления индекса.
Лучшие практики использования индексы
Индексы могут значительно улучшить производительность вашей SQLite базы данных, но их использование должно быть разумным. Вот несколько лучших практик, которые стоит рассмотреть при работе с индексами:
Когда и почему использовать индексы
-
Часто используемые колонки запроса: Использовать индексы на колонках, которые часто используются в запросах
SELECT
, особенно те, которые используются в чалахWHERE
,JOIN
иORDER BY
. Это porque индексирование этих колонок может значительно уменьшить время выполнения запроса. -
Ограничения уникальности: когда у вас есть колонки, которые должны содержать уникальные значения (как, например, имена пользователей или электронные адреса), создание индекса может эффективно закончить эту ограничение.
-
large datasets: для таблиц с большим количеством записей, индексы становятся всё более полезными. они позволяют быстро выполнять поиск, что важно для поддержания производительности при росте данных.
-
композитные индексы: рассмотрите создание композитных индексов для запросов, которые фильтруют или сортируют по нескольким колонкам. например, если вы часто ищут студентов по
имени
ивозрасту
, индекс на обоих колонках может оптимизировать такие запросы.
Потенциальные недостатки индексов
Несмотря на значительные преимущества индексов, существуют некоторые потенциальные недостатки:
-
Уменьшение скорости операций вставки/обновления: При вставке или обновлении записей в таблице с индексами SQLite также должен обновлять индекс, что может замедлить эти операции. Это связано с тем, что каждая операция вставки или обновления требует дополнительной нагрузки на поддержание структуры индекса.
-
Увеличение требований к запасу хранения: Индексы занимают дополнительное дисковое пространство. Для больших таблиц стоимость хранения может быть существенной. Учитывайте это при проектировании схемы базы данных, особенно для систем с ограниченными ресурсами хранения.
-
Управление сложным индексированием: Иметь слишком много индексов может усложнить управление базой данных. Это может привести к ситуациям, когда у вас есть избыточные индексы, которые скорее ухудшают производительность, чем улучшают ее. Регулярное обзор и оптимизация ваших индексов – это хорошая практика.
Индексы являются мощными инструментами для оптимизации запросов к базе данных, но требуют тщательного обдумывания. Найдение баланса между улучшением производительности чтения и потенциальной нагрузкой на операции записи – ключевая задача. Вот некоторые стратегии для достижения этого баланса:
-
Отслеживание производительности запросов: Используйте
EXPLAIN QUERY PLAN
SQLite для анализа того, как выполняются ваши запросы с индексами и без них. Это может помочь определить, какие индексы полезны, а какие могут быть излишни. -
Регулярное обслуживание: Периодически проверяйте ваши индексы и оценивайте, нужны ли они по-прежнему. Удалите избыточные или редко используемые индексы, чтобы оптимизировать операции с базой данных.
-
Проверка и оценка: перед внедрением индексов в производственную среду, проведите тщательные тесты, чтобы понять их влияние на операции чтения и записи.
Придерживаясь этих лучших практик, вы можете использовать преимущества индексации, уменьшая потенциальные недостатки, что Ultimately enhances the performance and efficiency of your SQLite database.
Как обрабатывать ошибки и исключения
В этой секции мы будем讨论如何 обрабатывать ошибки и исключения при работе с SQLite на Python. правильное обработка ошибок важно для сохранения целостности вашей базы данных и обеспечения предсказуемого поведения вашего приложения.
Ошибки при операциях с SQLite
При взаимодействии с SQLite базой данных могут возникать несколько общих ошибок:
-
Нарушения ограничений: Это происходит, когда вы пытаетесь вставить или обновить данные, которые нарушают ограничения базы данных, такие как уникальность primary key или ограничения foreign key. Например, попытка вставить дублирующийся primary key вызовет ошибку.
-
Ошибки несоответствия типов данных: Попытка вставить данные неверного типа (например, вставка строки вместо ожидаемого числа) может привести к ошибке.
-
Ошибки блокировки базы данных: Если база данных используется другим процессом или соединением, попытка ее обработки может привести к ошибке “база данных заблокирована”.
-
Ошибки синтаксиса: Ошибки в вашем синтаксисе SQL приведут к ошибкам при попытке выполнить ваши команды.
Как использовать исключения в Python.
Python имеет встроенные механизмы обработки исключений (try
и except
), которые являются необходимыми для управления ошибками в операциях SQLite. Используя эти конструкции, вы можете поймать исключения и соответствующим образом ответить на них, не вызывая сбой вашего программы.
Вот пример базового обработки ошибок при вставке данных в базу данных:
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) # Дублирующая запись
В этом примере:
-
Мы ловим
IntegrityError
, который возникает при нарушениях таких как уникальные ограничения. -
Мы ловим
OperationalError
для общих проблем связанных с базой данных (например, ошибки блокировки базы данных). -
Также у нас есть общий блок
except
для обработки любых неожиданных исключений.
Вывод:
Added customer: Vishakha with balance: 100.0
Error: Integrity constraint violated - UNIQUE constraint failed: Customers.name
Лучшие практики для обеспечения целостности базы данных
-
Использование транзакций
: всегда использовать транзакции (как было обсуждено в предыдущей секции), когда вы выполняете несколько связанных операций. Это помогает обеспечить, что либо все операции успешно выполняются, либо их ни одна не выполняется, сохраняя последовательность.
-
Проверка входных данных: до выполнения SQL-команд проверьте входные данные, чтобы убедиться, что они соответствуют ожидаемым критериям (например, correct types, within allowable ranges).
-
Обработка специфических исключений: всегда捕获 специфические исключения, чтобы адекватно обрабатывать различные типы ошибок. Это позволяет более ясную обработку ошибок и отладку.
-
Журналирование ошибок: вместо того, чтобы просто выводить ошибки на консоль, подумайте о том, чтобы записывать их в файл или систему мониторинга. Это поможет вам отслеживать проблемы в производстве.
-
Плавная деградация: проектируйте вашу приложение так, чтобы оно отлично обрабатывало ошибки. Если операция завершается неудачей, предоставляйте пользователю смысловое сообщение, а не вылетайте приложение.
-
Регулярно сохраняйте данные: регулярно сохраняйте вашу базу данных, чтобы предотвратить потерю данных в случае критических ошибок или порче.
-
Используйте подготовленные запросы: подготовленные запросы помогают защитить от атак SQL injection и могут также обеспечить лучшую производительность для повторяющихся запросов.
Как экспортировать и импортировать данные [дополнительный раздел]
В этом разделе мы leanr如何 извлечь данные из SQLite базы данных в распространенные форматы, такие как CSV и JSON, а также как импортировать данные в SQLite из этих форматов с использованием Python. Это удобно для обмена данными, резервного копирования и интеграции с другими приложениями.
Экспорт данных из SQLite в CSV
Экспорт данных в CSV (записи разделенные запятой) файл является простым с Python’ом встроенными библиотеками. 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), который является популярным форматом для обмена данными, особенно в веб-приложениях.
Вот пример, как экспортировать данные в 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')
Как импортировать данные в SQLite из CSV
Вы также можете импортировать данные из CSV файла в SQLite базу данных. Это удобно для заполнения базы данными существующими наборами данных.
Тут описано, как импортировать данные из 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')
Как импортировать данные в SQLite из JSON
Также импортировать данные из 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 бесплатно, используя инструмент Generator TOC.
Source:
https://www.freecodecamp.org/news/work-with-sqlite-in-python-handbook/