SQLite — PythonRu https://pythonru.com Изучайте Python на русском: учебные руководства Python для разработчиков с разным уровнем знаний, рекомендации книг и курсов Python, новости, примеры кода, статьи и уроки Mon, 28 Dec 2020 09:20:04 +0000 ru-RU hourly 1 https://pythonru.com/wp-content/uploads/2018/11/cropped-pythonru-icon-32x32.png SQLite — PythonRu https://pythonru.com 32 32 Работа с датой и временем в SQLite https://pythonru.com/biblioteki/rabota-s-datoj-i-vremenem-v-sqlite Sat, 09 Jan 2021 13:19:00 +0000 https://pythonru.com/?p=4383 В этом примере рассмотрим, как работать с датами и временем в SQLite и Python. Часто требуется вставлять дату или объект datetime из Python в таблицу SQLite. Также нужно читать данные в формате datetime, сохраненные в SQLite, и конвертировать их в объекты соответствующего типа в Python для использования в программе.

Перед работой с программой нужно убедиться, что у вас есть база данных из прошлых уроков sqlite_python.db.

В этом примере будет использоваться таблица new_developers.

Пример вставки/получения объекта DateTime

Обычно при выполнении запроса на вставку объекта datetime модуль sqlite3 в Python конвертирует его в строковый формат. То же самое происходит при получении данных из таблицы — они возвращаются в строковом формате. Разберем на простом примере.


import sqlite3, datetime

def add_developer(dev_id, name, joining_date):
try:
sqlite_connection = sqlite3.connect('sqlite_python.db')
cursor = sqlite_connection.cursor()
print("Подключен к SQLite")

sqlite_create_table_query = '''CREATE TABLE new_developers (
id INTEGER PRIMARY KEY,
name TEXT NOT NULL,
joiningDate timestamp);'''

cursor = sqlite_connection.cursor()
cursor.execute(sqlite_create_table_query)

# вставить данные разработчика
sqlite_insert_with_param = """INSERT INTO 'new_developers'
('id', 'name', 'joiningDate')
VALUES (?, ?, ?);"""

data_tuple = (dev_id, name, joining_date)
cursor.execute(sqlite_insert_with_param, data_tuple)
sqlite_connection.commit()
print("Разработчик успешно добавлен \n")

# получить данные разработчика
sqlite_select_query = """SELECT name, joiningDate from new_developers where id = ?"""
cursor.execute(sqlite_select_query, (1,))
records = cursor.fetchall()

for row in records:
developer= row[0]
joining_date = row[1]
print(developer, "присоединился", joining_date)
print("тип даты", type(joining_date))
cursor.close()

except sqlite3.Error as error:
print("Ошибка при работе с SQLite", error)
finally:
if sqlite_connection:
sqlite_connection.close()
print("Соединение с SQLite закрыто")

add_developer(1, 'Mark', datetime.datetime.now())

Вывод:

Подключен к SQLite
Разработчик успешно добавлен 

Mark присоединился 2020-12-28 10:58:48.828803
тип даты <class 'str'>
Соединение с SQLite закрыто

Как можно видеть, в таблицу был вставлен объект даты, но после получения он стал строкой. Однако это не мешает конвертировать результат обратно в объект даты.

Для этого используется detect_types с PARSE_DECLTYPES и PARSE_COLNAMES в качестве аргументов в методе connect модуля sqlite3.

sqlite3.PARSE_DECLTYPES

Эта константа используется как значение параметра detect_types метода connect().

Если использовать этот параметр в методе connect(), то модуль sqlite3 будет парсить тип каждой получаемой колонки.

После парсинга используется словарь конвертации типов для поиска выполнения конкретной функции конвертации.

sqlite3.PARSE_COLNAMES

Эта константа нужна для того же параметра.

При ее использовании интерфейс SQLite сохранит значения имени каждой возвращаемой колонки. После этого можно аналогично использовать словарь для конвертации в нужный тип.

Посмотрим на следующий пример. В нем при считывании объекта datetime из таблицы SQLite нужно получить объединяющий тип — datetime.


import sqlite3, datetime

def add_developer(dev_id, name, joining_date):
try:
sqlite_connection = sqlite3.connect('sqlite_python.db',
detect_types=sqlite3.PARSE_DECLTYPES |
sqlite3.PARSE_COLNAMES)
cursor = sqlite_connection.cursor()
print("Подключен к SQLite")

sqlite_create_table_query = '''CREATE TABLE new_developers2 (
id INTEGER PRIMARY KEY,
name TEXT NOT NULL,
joiningDate timestamp);'''

cursor = sqlite_connection.cursor()
cursor.execute(sqlite_create_table_query)

# вставить данные разработчика
sqlite_insert_with_param = """INSERT INTO 'new_developers2'
('id', 'name', 'joiningDate')
VALUES (?, ?, ?);"""

data_tuple = (dev_id, name, joining_date)
cursor.execute(sqlite_insert_with_param, data_tuple)
sqlite_connection.commit()
print("Разработчик успешно добавлен \n")

# получить данные разработчика
sqlite_select_query = """SELECT name, joiningDate from new_developers2 where id = ?"""
cursor.execute(sqlite_select_query, (1,))
records = cursor.fetchall()

for row in records:
developer= row[0]
joining_date = row[1]
print(developer, "присоединился", joining_date)
print("тип даты", type(joining_date))
cursor.close()

except sqlite3.Error as error:
print("Ошибка при работе с SQLite", error)
finally:
if sqlite_connection:
sqlite_connection.close()
print("Соединение с SQLite закрыто")

add_developer(1, 'Mark', datetime.datetime.now())

Вывод:

Подключен к SQLite
Разработчик успешно добавлен 

Mark присоединился 2020-12-28 11:11:01.304116
тип даты <class 'datetime.datetime'>
Соединение с SQLite закрыто

В результате вернувшиеся данные из таблицы представлены типом datetime.datetime.

]]>
Работа с изображениями и файлами в SQLite https://pythonru.com/biblioteki/rabota-s-izobrazhenijami-i-fajlami-v-sqlite Sat, 02 Jan 2021 13:21:00 +0000 https://pythonru.com/?p=4337 В этом материале вы узнаете, как вставлять и получать BLOB-данные из таблицы SQLite с помощью Python и модуля sqlite3.

  • В качестве бинарных данных могут выступать файлы с любым расширением, изображения, видео или другие медиа;
  • BLOB-данные можно считывать из таблицы SQLite.

Перед выполнением операций над BLOB-данными убедитесь, что вы знаете название таблицы SQLite. Для хранения этой информации нужно или создать новую, или изменить существующую, добавив колонку соответствующего типа.

В этом примере будет использоваться таблица new_employee. Ее можно создать с помощью следующего скрипта:

CREATE TABLE new_employee (id INTEGER PRIMARY KEY, name TEXT NOT NULL, photo BLOB NOT NULL, resume BLOB NOT NULL);

Эта таблица содержит две BLOB-колонки:

  • Колонка photo для хранения изображения сотрудника.
  • Колонка resume для хранения файла резюме.

Но стоит также разобраться с тем, что же такое BLOB.

Что такое BLOB

BLOB (large binary object — «большой бинарный объект») — это тип данных, который используется для хранения «тяжелых» файлов, таких как изображения, видео, музыка, документы и так далее. Перед сохранением в базе данных эти файлы нужно конвертировать в бинарные данные — то есть, массив байтов.

Вставка изображений и файлов в таблицу

Вставим изображение и резюме сотрудника в таблицу new_employee. Для этого требуется выполнить следующие шаги:

  • Установить SQLite-соединение с базой данных из Python;
  • Создать объект cursor из объекта соединения;
  • Создать INSERT-запрос. На этом этапе нужно знать названия таблицы и колонки, в которую будет выполняться вставка;
  • Создать функцию для конвертации цифровых данных (например, изображений или файлов) в бинарные;
  • Выполнить INSERT-запрос с помощью cursor.execute();
  • После успешного завершения операции закоммитить сохранения в базу данных;
  • Закрыть объект cursor и соединение;
  • Перехватить любые SQL-исключения.

Посмотрим на пример:


import sqlite3

def convert_to_binary_data(filename):
# Преобразование данных в двоичный формат
with open(filename, 'rb') as file:
blob_data = file.read()
return blob_data

def insert_blob(emp_id, name, photo, resume_file):
try:
sqlite_connection = sqlite3.connect('sqlite_python.db')
cursor = sqlite_connection.cursor()
print("Подключен к SQLite")

sqlite_insert_blob_query = """INSERT INTO new_employee
(id, name, photo, resume) VALUES (?, ?, ?, ?)"""

emp_photo = convert_to_binary_data(photo)
resume = convert_to_binary_data(resume_file)
# Преобразование данных в формат кортежа
data_tuple = (emp_id, name, emp_photo, resume)
cursor.execute(sqlite_insert_blob_query, data_tuple)
sqlite_connection.commit()
print("Изображение и файл успешно вставлены как BLOB в таблиу")
cursor.close()

except sqlite3.Error as error:
print("Ошибка при работе с SQLite", error)
finally:
if sqlite_connection:
sqlite_connection.close()
print("Соединение с SQLite закрыто")

insert_blob(1, "Smith", "smith.jpg", "smith_resume.docx")
insert_blob(2, "David", "david.jpg", "david_resume.docx")

Вывод:

Подключен к SQLite
Изображение и файл успешно вставлены как BLOB в таблиу
Соединение с SQLite закрыто
Подключен к SQLite
Изображение и файл успешно вставлены как BLOB в таблиу
Соединение с SQLite закрыто

Вот как выглядит таблица после вставки данных:

Работа с изображениями и файлами в SQLite
  • В примере были вставлены id сотрудника, имя, фото и файл с резюме. Для последних двух были переданы местоположения файлов, так что программа смогла считать их и конвертировать в бинарные данные
  • Как можно явно увидеть, изображение и файл конвертировались в бинарный формат в процессе чтения данных в режиме rb. И только после этого данные были вставлены в колонку BLOB. Также был использован запрос с параметрами для вставки динамических данных в таблицу.

Получение изображения и файла, сохраненных в виде BLOB

Предположим, данные, которые хранятся в виде BLOB в базе данных, нужно получить, записать в файл на диске и открыть в привычном виде. Как это делается?

В этом примере считаем изображение сотрудника и файл с резюме из SQLite-таблицы.

Для этого нужно проделать следующие шаги:

  • Установить SQLite-соединение с базой данных из Python;
  • Создать объект cursor из объекта соединения;
  • Создать SELECT-запрос для получения BLOB-колонок из таблицы;
  • Использовать cursor.fetchall() для получения всех строк и перебора по ним;
  • Создать функцию для конвертации BLOB-данных в нужный формат и записать готовые файлы на диск;
  • Закрыть объект cursor и соединение.

import sqlite3, os

def write_to_file(data, filename):
# Преобразование двоичных данных в нужный формат
with open(filename, 'wb') as file:
file.write(data)
print("Данный из blob сохранены в: ", filename, "\n")

def read_blob_data(emp_id):
try:
sqlite_connection = sqlite3.connect('sqlite_python.db')
cursor = sqlite_connection.cursor()
print("Подключен к SQLite")

sql_fetch_blob_query = """SELECT * from new_employee where id = ?"""
cursor.execute(sql_fetch_blob_query, (emp_id,))
record = cursor.fetchall()
for row in record:
print("Id = ", row[0], "Name = ", row[1])
name = row[1]
photo = row[2]
resume_file = row[3]

print("Сохранение изображения сотрудника и резюме на диске \n")
photo_path = os.path.join("db_data", name + ".jpg")
resume_path = os.path.join("db_data", name + "_resume.txt")
write_to_file(photo, photo_path)
write_to_file(resume_file, resume_path)
cursor.close()

except sqlite3.Error as error:
print("Ошибка при работе с SQLite", error)
finally:
if sqlite_connection:
sqlite_connection.close()
print("Соединение с SQLite закрыто")

read_blob_data(1)
read_blob_data(2)

Вывод:

Подключен к SQLite
Id =  1 Name =  Smith
Сохранение изображения сотрудника и резюме на диске 

Данный из blob сохранены в:  db_data\Smith.jpg 

Данный из blob сохранены в:  db_data\Smith_resume.txt 

Соединение с SQLite закрыто
Подключен к SQLite
Id =  2 Name =  David
Сохранение изображения сотрудника и резюме на диске 

Данный из blob сохранены в:  db_data\David.jpg 

Данный из blob сохранены в:  db_data\David_resume.txt 

Соединение с SQLite закрыто

Изображения и файлы действительно сохранились на диске.

Получение изображения и файла, сохраненных в виде BLOB

Примечание: для копирования бинарных данных на диск они сперва должны быть конвертированы в нужный формат. В этом примере форматами были .jpg и .txt.

]]>
Создание или переопределение SQL-функций в SQLite https://pythonru.com/biblioteki/sozdanie-ili-pereopredelenie-sql-funkcij-v-sqlite Sat, 26 Dec 2020 13:13:00 +0000 https://pythonru.com/?p=4212 В таких базах данных, как MySQL, MSSQL и PostgreSQL, есть возможность создавать функции и хранимые процедуры, но у SQLite такой возможности нет. Таким образом, CREATE FUNCTION и CREATE PROCEDURE с этой базой данных работать не будут. В этом материале рассмотрим, как создавать или переиспользовать SQL-функции из Python.

C API базы данных SQLite дает возможность создавать пользовательские функции или переопределять поведение существующих. Модуль sqlite3 — это всего лишь оболочка для этого C API, которая предоставляет возможность создавать или переопределять SQLite-функции из Python.

В этой статье мы рассмотрим:

  • Использовать connection.create_function() из sqlite3 в Python для создания и переопределения функций в SQLite;
  • Использовать connection.create_aggregate() для создания агрегатных функций в SQLite.

Создание SQL-функций из Python для SQLite

В определенных случаях возникает необходимость совершать определенные вещи при выполнении SQL-запроса, особенно, если это обновление или получение данных. В таких случаях на помощь приходят пользовательские функции. Например, при получении имени пользователя нужно, чтобы оно вернулось в верхнем регистре.

В SQLite есть масса встроенных функций: LENGTH, LOWER, UPPER, SUBSTR, REPLACE и другие. Добавим к этому списку TOTITLE для конвертации любой строки и в строку с заглавными буквами.

Для начала нужно разобраться с connection.create_function().

Синтаксис:

create_function(name, num_params, func)

Функция принимает три аргумента:

  • name — имя функции
  • num_params — количество параметров, которые функция принимает
  • func — функция Python, которая вызывается внутри запроса

Эта функция создает пользовательскую функцию, которую можно использовать в инструкциях SQL, ссылаясь на ее name.

Примечание: если в качестве параметра num_params передать значение -1, то функция будет принимать любое количество аргументов. connection.create_function() может возвращать любые типы, поддерживаемые SQLite: bytes, str, int, float и None.

Создадим новую функцию в SQLite с помощью connection.create_function().


import sqlite3

def _to_title_case(string):
return str(string).title()

def get_developer_name(dev_id):
try:
sqlite_connection = sqlite3.connect('sqlite_python.db')
cursor = sqlite_connection.cursor()
print("Подключен к SQLite")

sqlite_connection.create_function("TOTILECASE", 1, _to_title_case)
select_query = "SELECT TOTILECASE(name) FROM sqlitedb_developers where id = ?"
cursor.execute(select_query, (dev_id,))
name = cursor.fetchone()
print("Имя разработчика", name)
cursor.close()

except sqlite3.Error as error:
print("Ошибка при работе с SQLite", error)
finally:
if sqlite_connection:
sqlite_connection.close()
print("Соединение с SQLite закрыто")

get_developer_name(2)

Вывод:

Подключен к SQLite
Имя разработчика ('Viktoria',)
Соединение с SQLite закрыто

Разбор примера в подробностях

В прошлом разделе была создана функция _to_title_case, которая принимает строку в качестве входящего значения и конвертирует ее в строку с заглавными буквами.

import sqlite3:

  • Эта строка импортирует модуль sqlite3 в программу.
  • С помощью классов и методов модуля sqlite3 можно взаимодействовать с базой данных SQLite.

sqlite3.connect() и connection.cursor():

  • С помощью sqlite3.connect() устанавливается соединение с базой данных.
  • Дальше метод connection.cursor() используется для получения объекта cursor из объекта соединения.

сonnection.create_function():

  • После этого вызывается create_function из класса connection. В нее передаются три аргумента: название функции, количество параметров, которые будет принимать _to_title_case и функция Python, которая будет вызываться как SQL-функция.
  • После этого функция TOTITLECASE вызывается в запросе SELECT для получения имени разработчика в виде строки с заглавными буквами.

cursor.execute():

  • Выполняем запрос с помощью метода execute() объекта cursor и получаем имя с помощью cursor.fetchone().

Наконец, объекты cursor и connection закрываются в блоке finally после завершения операции обновления.

Переопределение существующих функций SQLite

Иногда нужно переопределить уже существующие функции. Например, при возвращении имени пользователя необходимо, чтобы оно было в верхнем регистре.

В качестве демонстрации конвертируем встроенную в SQLite функцию LOWER в UPPER, чтобы при ее вызове она превращала входящие данные в верхний регистр.

Создадим новое определение для функции lower() с помощью метода connection.create_function(). Таким образом мы перезаписываем уже существующую реализацию функции lower().


import sqlite3

def lower(string):
return str(string).upper()

def get_developer_name(dev_id):
try:
sqlite_connection = sqlite3.connect('sqlite_python.db')
cursor = sqlite_connection.cursor()
print("Подключен к SQLite")

sqlite_connection.create_function("lower", 1, lower)
select_query = "SELECT lower(name) FROM sqlitedb_developers where id = ?"
cursor.execute(select_query, (dev_id,))
name = cursor.fetchone()
print("Имя разработчика", name)
cursor.close()

except sqlite3.Error as error:
print("Ошибка при работе с SQLite", error)
finally:
if sqlite_connection:
sqlite_connection.close()
print("Соединение с SQLite закрыто")

get_developer_name(1)

Вывод:

Подключен к SQLite
Имя разработчика ('OLEG',)
Соединение с SQLite закрыто
]]>
Удаление записей из таблицы SQLite https://pythonru.com/biblioteki/udalenija-zapisej-iz-tablicy-sqlite Sun, 20 Dec 2020 14:41:01 +0000 https://pythonru.com/?p=4197 Этот материал посвящен выполнению SQL-операции DELETE для SQLite-таблицы из Python-приложения.

В этой статье мы рассмотрим:

  • Удаление одной, нескольких или всех строк или колонок из SQLite-таблицы с помощью Python;
  • Использование запроса с параметрами для выполнения операции удаления из SQLite;
  • Коммит и отмена последней операции;
  • Массовое удаление в один запрос.

Подготовка

Перед выполнением следующих операций нужно знать название таблицы SQLite, а также ее колонок. В этом материале будет использоваться таблица sqlitedb_developers.

Пример удаления одной строки из SQLite-таблицы

Сейчас таблица sqlitedb_developers содержит шесть строк, а удалять будем разработчика, чей id равен 6. Вот что для этого нужно сделать:

  • Присоединиться к SQLite из Python;
  • Создать объект Cursor с помощью полученного в прошлом шаге объекта соединения SQLite;
  • Создать DELETE-запрос для SQLite. Именно на этом этапе нужно знать названия таблицы и колонок;
  • Выполнить DELETE-запрос с помощью cursor.execute();
  • После выполнения запроса необходимо закоммитить изменения в базу данных;
  • Закрыть соединение с базой данных;
  • Также важно не забыть перехватить исключения, которые могут возникнуть;
  • Наконец, проверить результат операции.

Пример:


import sqlite3

def delete_record():
try:
sqlite_connection = sqlite3.connect('sqlite_python.db')
cursor = sqlite_connection.cursor()
print("Подключен к SQLite")

sql_delete_query = """DELETE from sqlitedb_developers where id = 6"""
cursor.execute(sql_delete_query)
sqlite_connection.commit()
print("Запись успешно удалена")
cursor.close()

except sqlite3.Error as error:
print("Ошибка при работе с SQLite", error)
finally:
if sqlite_connection:
sqlite_connection.close()
print("Соединение с SQLite закрыто")

delete_record()

Вывод: таблица sqlitedb_developers после удаления строки из Python.

Подключен к SQLite
Запись успешно удалена
Соединение с SQLite закрыто

Разбор примера в подробностях

import sqlite3:

  • На этой строке модуль sqlite3 импортируется в программу;
  • С помощью классов и методов sqlite3 можно взаимодействовать с базой данных SQLite.

sqlite3.connect() и connection.cursor():

  • С помощью sqlite3.connect() устанавливается соединение с базой данных SQLite из Python;
  • Дальше используется sqliteConnection.cursor() для получения объекта Cursor.

После этого создается DELETE-запрос для удаления шестой строки в таблице (для разработчика с id равным 6). В запросе этот разработчик упоминается.

cursor.execute():

  • Выполняется операция из DELETE-запроса с помощью метода execute() объекта Cursor;
  • После успешного удаления записи изменения коммитятся в базу данных с помощью connection.commit().

Наконец, закрываются Cursor и SQLite-соединение в блоке finally.

Примечание: если выполняется несколько операций удаления, и есть необходимость отменить все изменения в случае неудачи хотя бы с одной из них, нужно использовать функцию rollback() класса соединения для отмены. Эту функцию стоит применять внутри блока except.

Использование переменных в запросах для удаления строки

В большинстве случаев удалять строки из таблицы SQLite нужно с помощью ключа, который передается уже во время работы программы. Например, когда пользователь удаляет свою подписку, запись о нем нужно удалить из таблицы.

В таких случаях требуется использовать запрос с параметрами. В таких запросах на месте будущих значений ставятся заполнители (?). Это помогает удалять записи, получая значения во время работы программы, и избегать проблем SQL-инъекций. Вот пример с удалением разработчика с id=5.


import sqlite3

def delete_sqlite_record(dev_id):
try:
sqlite_connection = sqlite3.connect('sqlite_python.db')
cursor = sqlite_connection.cursor()
print("Подключен к SQLite")

sql_update_query = """DELETE from sqlitedb_developers where id = ?"""
cursor.execute(sql_update_query, (dev_id, ))
sqlite_connection.commit()
print("Запись успешно удалена")
cursor.close()

except sqlite3.Error as error:
print("Ошибка при работе с SQLite", error)
finally:
if sqlite_connection:
sqlite_connection.close()
print("Соединение с SQLite закрыто")

delete_sqlite_record(5)

Вывод: таблица sqlitedb_developers после удаления строки с помощью запроса с параметрами.

Подключен к SQLite
Запись успешно удалена
Соединение с SQLite закрыто

Разберем последний пример:

  • Запрос с параметрами использовался, чтобы получить id разработчика во время работы программы и подставить его на место ?. Он определяет id записи, которая будет удалена.
  • После этого создается кортеж данных с помощью переменных Python.
  • Дальше DELETE-запрос вместе с данными передается в метод cursor.execute().
  • Наконец, изменения сохраняются в базе данных с помощью метода commit() класса Connection.

Операция Delete для удаления нескольких строк

В примере выше был использован метод execute() объекта Cursor для удаления одной записи, но часто приходится удалять сразу несколько одновременно.

Вместо выполнения запроса DELETE каждый раз для каждой записи, можно выполнить операцию массового удаления в одном запросе. Удалить несколько записей из SQLite-таблицы в один запрос можно с помощью метода cursor.executemany().

Метод cursor.executemany(query, seq_param) принимает два аргумента: SQL-запрос и список записей для удаления.

Посмотрим на следующий пример. В нем удаляются сразу три разработчика.


import sqlite3

def delete_multiple_records(ids_list):
try:
sqlite_connection = sqlite3.connect('sqlite_python.db')
cursor = sqlite_connection.cursor()
print("Подключен к SQLite")

sqlite_update_query = """DELETE from sqlitedb_developers where id = ?"""
cursor.executemany(sqlite_update_query, ids_list)
sqlite_connection.commit()
print("Удалено записей:", cursor.rowcount)
sqlite_connection.commit()
cursor.close()

except sqlite3.Error as error:
print("Ошибка при работе с SQLite", error)
finally:
if sqlite_connection:
sqlite_connection.close()
print("Соединение с SQLite закрыто")

ids_to_delete = [(4,),(3,)]
delete_multiple_records(ids_to_delete)
Подключен к SQLite
далено записей: 2
Соединение с SQLite закрыто

Разберем последний пример:

  • После соединения с базой данных SQLite готовится SQL-запрос с параметрами и одним заполнителем. Вместе с ним также передается список id в формате кортежа.
  • Каждый элемент списка — это всего лишь кортеж каждой строки. Каждый кортеж содержит id разработчика. В этом примере три кортежа — то есть, три разработчика.
  • Дальше вызывается cursor.executemany(sqlite_delete_query, ids_list) для удаления нескольких записей из таблицы. И запрос, и список id передаются cursor.executemany() в качестве аргументов.
  • Чтобы увидеть количество затронутых записей, можно использовать метод cursor.rowcount. Наконец, изменения сохраняются в базу данных с помощью метода commit класса Connection.
]]>
Обновление данных в SQLite-таблице https://pythonru.com/biblioteki/obnovlenie-dannyh-v-sqlite-tablice Sun, 13 Dec 2020 10:36:00 +0000 https://pythonru.com/?p=4137 Этот материал посвящен использованию запроса UPDATE для обновления SQLite-таблицы из приложения, написанного на Python. Вы узнаете, как использовать встроенный модуль sqlite3 для обновления SQLite-таблицы.

В этой статье мы рассмотрим:

  • Обновление одной или нескольких колонок.
  • Использование запроса с параметрами для передачи значения во время работы программы при запросе Update.
  • Коммит и откат операции обновления.
  • Обновление колонки с помощью значений date-time и timestamp.
  • Выполнение массового обновления в одном запросе.

Подготовка

Перед выполнением следующих операций обновления таблицы SQLite нужно убедиться, что вам известно ее название, а также названия колонок.

В этом примере будет использоваться таблица sqlitedb_developers. Она была создана в первой части руководства по sqlite3 и заполнена во второй.

Обновления одной записи в таблице SQLite

Сейчас таблица sqlitedb_developers содержит шесть строк, поэтому обновим зарплату разработчика с id 4. Для выполнения запроса UPDATE из Python нужно выполнить следующие шаги:

  • Сперва нужно установить SQLite-соединение из Python.
  • Дальше необходимо создать объект cursor с помощью объекта соединения.
  • После этого – создать запрос UPDATE. Для этого нужно знать названия таблицы и колонки, которую потребуется обновить.
  • Дальше запрос выполняется с помощью cursor.execute().
  • После успешного завершения запроса нужно не забыть закоммитить изменения в базу данных.
  • Соединение с базой данных закрывается.
  • Также важно не забыть перехватывать все исключения SQLite.
  • Наконец, нужно убедиться, что операция прошло успешно, получив данные из таблицы.

Посмотрим на программу.


import sqlite3

def update_sqlite_table():
try:
sqlite_connection = sqlite3.connect('sqlite_python.db')
cursor = sqlite_connection.cursor()
print("Подключен к SQLite")

sql_update_query = """Update sqlitedb_developers set salary = 10000 where id = 4"""
cursor.execute(sql_update_query)
sqlite_connection.commit()
print("Запись успешно обновлена")
cursor.close()

except sqlite3.Error as error:
print("Ошибка при работе с SQLite", error)
finally:
if sqlite_connection:
sqlite_connection.close()
print("Соединение с SQLite закрыто")

update_sqlite_table()

Вывод: таблица sqlitedb_developers после обновления строки из Python.

Подключен к SQLite
Запись успешно обновлена
Соединение с SQLite закрыто

Проверить результат можно, посмотрев данные из таблицы.

Обновления одной записи в таблице SQLite

Разбор примера в подробностях

import sqlite3:

  • Эта строка импортирует модуль sqlite3 в программу.
  • С помощью классов и методов из модуля можно взаимодействовать с базой данных.

sqlite3.connect() и connection.cursor():

  • С помощью sqlite3.connect() устанавливается соединение с базой данных SQLite из Python.
  • Дальше метод connection.cursor() используется для получения объекта сursor из объекта соединения.

После этого создается запрос UPDATE для обновления строки в таблицы. В нем указываются название колонки и новое значение. В таблице пять колонок, но код обновляет только одну из них – ту, что содержит данные о зарплате.

cursor.execute():

  • Операция, сохраненная в запросе UPDATE, выполняется с помощью метода execute() объекта сursor.
  • connection.commit() применяется для сохранения в базе данных.

Наконец, закрываются объекты сursor и соединение в блоке finally после завершения операции обновления.

Примечание: если выполняется операция массового обновления и есть необходимость откатить изменения в случае ошибки хотя бы при одном, нужно использовать функцию rollback() класса connection. Ее необходимо применить в блоке except.

Использование переменных Python в запросе UPDATE

Большую часть времени обновление таблицы нужно выполнять с помощью значений, получаемых при работе программы. Например, когда пользователи обновляют свой профиль через графический интерфейс, нужно обновить заданные ими значения в соответствующей таблице.

В таком случае рекомендуется использовать запрос с параметрами. Такие запросы используют заполнители (?) прямо внутри инструкций SQL. Это помогает обновлять значения с помощью переменных, а также предотвращать SQL-инъекции.


import sqlite3

def update_sqlite_table(dev_id, salary):
try:
sqlite_connection = sqlite3.connect('sqlite_python.db')
cursor = sqlite_connection.cursor()
print("Подключен к SQLite")

sql_update_query = """Update sqlitedb_developers set salary = ? where id = ?"""
data = (salary, dev_id)
cursor.execute(sql_update_query, data)
sqlite_connection.commit()
print("Запись успешно обновлена")
cursor.close()

except sqlite3.Error as error:
print("Ошибка при работе с SQLite", error)
finally:
if sqlite_connection:
sqlite_connection.close()
print("Соединение с SQLite закрыто")

update_sqlite_table(3, 7500)

Вывод: таблица sqlitedb_deveopers после обновления с помощью переменной Python и запроса с параметрами.

Подключен к SQLite
Запись успешно обновлена
Соединение с SQLite закрыто

Подтвердить операцию можно, получив данные из SQLite-таблицы из Python.

Использование переменных Python в запросе UPDATE

Разберем код:

  • Запрос с параметрами был использован для того, чтобы получить значения при работе программы и установить их на места заполнителей. В этом случае один из них отвечает за колонку «salary», а второй – колонку id.
  • После этого готовится кортеж с данными из двух переменных Python в определенном порядке. Этот кортеж вместе с запросом передается в метод cursor.execute(). Важно помнить, что в данном случае порядок переменных в кортеже играет значение.
  • В конце изменения закрепляются с помощью метода commit класса connection.

Обновление нескольких строк SQLite-таблицы

В последнем примере использовался метод execute() объекта cursor для обновления одного значения, но иногда в приложениях Python нужно обновить несколько строк. Например, нужно увеличить зарплату большинства разработчиков на 20%.

Вместе выполнения операции UPDATE каждый раз для каждой записи можно выполнить массовое обновление в один запрос. Изменить несколько записей в таблице SQLite в один запрос можно с помощью метода cursor.executemany().

Метод cursor.executemany(query, seq_param) принимает два аргумента: SQL-запрос и список записей для обновления.

Посмотрим на примере. Здесь обновляется зарплата 3 разработчиков.


import sqlite3

def update_multiple_records(record_list):
try:
sqlite_connection = sqlite3.connect('sqlite_python.db')
cursor = sqlite_connection.cursor()
print("Подключен к SQLite")

sqlite_update_query = """Update sqlitedb_developers set salary = ? where id = ?"""
cursor.executemany(sqlite_update_query, record_list)
sqlite_connection.commit()
print("Записей", cursor.rowcount, ". Успешно обновлены")
sqlite_connection.commit()
cursor.close()

except sqlite3.Error as error:
print("Ошибка при работе с SQLite", error)
finally:
if sqlite_connection:
sqlite_connection.close()
print("Соединение с SQLite закрыто")

records_to_update = [(9700, 4), (7800, 5), (8400, 6)]
update_multiple_records(records_to_update)

Вывод: таблица sqlitedb_developers после обновления нескольких строк из Python.

Подключен к SQLite
Записей 3 . Успешно обновлены
Соединение с SQLite закрыто

Проверить результат можно, получив данные из таблицы из Python.

Обновление нескольких строк SQLite-таблицы

Разберем код:

  • После подключения к таблице SQLite готовится SQLite-запрос с двумя заполнителями (колонки salary и id), а также список записей для обновления в формате кортежа.
  • Каждый элемент – это кортеж для каждой записи. Каждый кортеж содержит два значения: зарплату и id разработчика.
  • Функция cursor.executemany(sqlite_update_query, record_list) вызывается для обновления нескольких строк таблицы SQLite.
  • Чтобы узнать, какое количество записей было изменено, используется функция cursor.rowcount. Наконец, данные сохраняются в базу данных с помощью метода commit класса connection.

Обновление нескольких колонок таблицы SQLite

Можно обновить несколько колонок таблицы SQLite в один запрос. Для этого нужно лишь подготовить запрос с параметрами и заполнителями. Посмотрим на примере.

Вывод: таблица sqlitedb_developers после обновления нескольких колонок.


import sqlite3

def update_multiple_columns(dev_id, salary, email):
try:
sqlite_connection = sqlite3.connect('sqlite_python.db')
cursor = sqlite_connection.cursor()
print("Подключен к SQLite")

sqlite_update_query = """Update sqlitedb_developers set salary = ?, email = ? where id = ?"""
column_values = (salary, email, dev_id)
cursor.execute(sqlite_update_query, column_values)
sqlite_connection.commit()
print("Несколько столбцов успешно обновлены")
sqlite_connection.commit()
cursor.close()

except sqlite3.Error as error:
print("Ошибка при работе с SQLite", error)
finally:
if sqlite_connection:
sqlite_connection.close()
print("Соединение с SQLite закрыто")

update_multiple_columns(3, 2500, 'bec9988@gmail.com')
Подключен к SQLite
Несколько столбцов успешно обновлены
Соединение с SQLite закрыто

]]>
Получение данных из таблицы SQLite https://pythonru.com/biblioteki/poluchenie-dannyh-iz-tablicy-sqlite Sat, 05 Dec 2020 11:53:51 +0000 https://pythonru.com/?p=4112 В этом материале речь пойдет о команде SELECT для получения данных из таблицы SQLite в приложении Python. Вы узнаете, как доставать строки с данными благодаря встроенному модулю sqlite3.

В этой статье мы будем:

  • Получать все строки с помощью с помощью cursor.fetchall().
  • Использовать cursor.fetchmany(size) для получения ограниченного количества строк, а также cursor.fetchone() — для одной.
  • Использовать переменные Python в запросе SQLite для передачи динамических данных.

Подготовка

Перед работой с этой Python-программой нужно убедиться, что вы знаете название и подробности о колонках той SQLite-таблицы, с которой предстоит работать.

В этом примере будет использоваться таблица sqlitedb_developers. Она была создана в первой части руководства по sqlite3 и заполнена во второй.

Шаги для получения строк из таблицы SQLite

Для выполнения операции SELECT из Python нужно выполнить следующие шаги:

  • Установить соединение с базой данных SQLite из Python;
  • Создать запрос с инструкцией SELECT для SQLite. Именно на этом этапе понадобятся знания названия таблицы и подробностей о колонках;
  • Выполнить SELECT-запрос с помощью метода cursor.execute()
  • Получить строки с помощью объекта Cursor и метода cursor.fetchall();
  • Перебрать строки и получить для каждой ее соответствующее значение;
  • Закрыть объект Cursor и соединение с базой данных SQLite;
  • Перехватить любые исключения, которые могут возникнуть в процессе работы.

Пример программы на Python для получения всех строк из таблицы sqlitedb_developers.


import sqlite3

def read_sqlite_table(records):
try:
sqlite_connection = sqlite3.connect('sqlite_python.db')
cursor = sqlite_connection.cursor()
print("Подключен к SQLite")

sqlite_select_query = """SELECT * from sqlitedb_developers"""
cursor.execute(sqlite_select_query)
records = cursor.fetchall()
print("Всего строк: ", len(records))
print("Вывод каждой строки")
for row in records:
print("ID:", row[0])
print("Имя:", row[1])
print("Почта:", row[2])
print("Добавлен:", row[3])
print("Зарплата:", row[4], end="\n\n")

cursor.close()

except sqlite3.Error as error:
print("Ошибка при работе с SQLite", error)
finally:
if sqlite_connection:
sqlite_connection.close()
print("Соединение с SQLite закрыто")

read_sqlite_table()

Вывод:

Подключен к SQLite
Всего строк:   6
Вывод каждой строки
ID: 1
Имя: Oleg
Почта: oleg04@gmail.com
Добавлен: 2020-11-29
Зарплата: 8100.0

...

ID: 6
Имя: Nikita
Почта: aqillysso@gmail.com
Добавлен: 2020-11-27
Зарплата: 7400.0

Соединение с SQLite закрыто

В этом примере прямо отображаются строка и значение ее колонки. Если вам нужно использовать значения колонки в своей программе, то их можно сохранять в переменные Python. Для этого нужно написать, например, так: name = row[1].

Разбор примера

import sqlite3:

  • Эта строка импортирует в программу модуль sqlite3.
  • С помощью классов и методов из этого модуля можно прямо взаимодействовать с базой данных.

sqlite3.connect() и connection.cursor():

  • С помощью sqlite3.connect() устанавливается соединение с базой данных SQLite из Python.
  • После этого готовится SELECT-запрос для получения всех строк из таблицы sqlitedb_developers. Она содержит пять колонок.
  • Метод connection.cursor() используется для получения объекта Cursor из объекта соединения.

cursor.execute() и cursor.fetchall():

  • Выполняется SELECT-операция с помощью метода execute() объекта Cursor.
  • После успешного выполнения запроса используется метод cursor.fetchall() для получения всех записей таблицы sqlitedb_developers.
  • В конце используется цикл для перебора всех записей и вывода их по одному.

После того как все записи были получены, объект Cursor закрывается с помощью cursor.close(), а соединение с базой данных — с помощью sqliteConnection.close().

Примечание:

  • Используйте cursor.execute() для выполнения запроса.
  • cursor.fetchall() — получение всех строк.
  • cursor.fetchone() — для одной строки.
  • cursor.fetchmany(SIZE) — для ограниченного количества строк.

Использование переменных в качестве параметров Select-запроса

Часто есть необходимость передать переменную в SELECT-запрос для проверки определенного условия.

Предположим, приложение хочет сделать запрос для получения информации о разработчиках, используя их id. Для этого необходим запрос с параметрами. Это такой запрос, где внутри используются заполнители (?) на месте параметров, которые потом заменяются реальными значениями.

cursor.execute("SELECT salary FROM sqlitedb_developers WHERE id = "ID из программы")

Рассмотрим пример.


import sqlite3

def get_developer_info(id):
try:
sqlite_connection = sqlite3.connect('sqlite_python.db')
cursor = sqlite_connection.cursor()
print("Подключен к SQLite")

sql_select_query = """select * from sqlitedb_developers where id = ?"""
cursor.execute(sql_select_query, (id,))
records = cursor.fetchall()
print("Вывод ID ", id)
for row in records:
print("ID:", row[0])
print("Имя:", row[1])
print("Почта:", row[2])
print("Добавлен:", row[3])
print("Зарплата:", row[4], end="\n\n")

cursor.close()

except sqlite3.Error as error:
print("Ошибка при работе с SQLite", error)
finally:
if sqlite_connection:
sqlite_connection.close()
print("Соединение с SQLite закрыто")

get_developer_info(2)

Вывод:

Подключен к SQLite
Вывод ID  2
ID: 2
Имя: Viktoria
Почта: s_dom34@gmail.com
Добавлен: 2020-11-19
Зарплата: 6000.0

Соединение с SQLite закрыто

Получение нескольких строк из таблицы

В некоторых случаев попытка получить все строки из таблицы займет слишком много времени, особенно, если их там тысячи.

Для получения всех строк нужно больше ресурсов: памяти и времени обработки. А для улучшения производительности в таких случаях рекомендуется использовать метод fetchmany(size) класса сursor для получения фиксированного количество строк.

С помощью cursor.fetchmany(size) можно указать, сколько строк требуется прочесть. Рассмотрим на примере:


import sqlite3

def read_limited_rows(row_size):
try:
sqlite_connection = sqlite3.connect('sqlite_python.db')
cursor = sqlite_connection.cursor()
print("Подключен к SQLite")

sqlite_select_query = """SELECT * from sqlitedb_developers"""
cursor.execute(sqlite_select_query)
print("Чтение ", row_size, " строк")
records = cursor.fetchmany(row_size)
print("Вывод каждой строки \n")
for row in records:
print("ID:", row[0])
print("Имя:", row[1])
print("Почта:", row[2])
print("Добавлен:", row[3])
print("Зарплата:", row[4], end="\n\n")

cursor.close()

except sqlite3.Error as error:
print("Ошибка при работе с SQLite", error)
finally:
if sqlite_connection:
sqlite_connection.close()
print("Соединение с SQLite закрыто")

read_limited_rows(2)

Вывод:

Подключен к SQLite
Чтение  2  строк
Вывод каждой строки 

ID: 1
Имя: Oleg
Почта: oleg04@gmail.com
Добавлен: 2020-11-29
Зарплата: 8100.0

ID: 2
Имя: Viktoria
Почта: s_dom34@gmail.com
Добавлен: 2020-11-19
Зарплата: 6000.0

Соединение с SQLite закрыто

Примечание: в этой программе был сделан запрос на получение двух записей. Но если в таблице их меньше, то вернется именно такое количество.

Получение одной строки из таблицы

Когда нужно получить одну строку из таблицы SQLite, стоит использовать метод fetchone() класса cursor. Этот метод необходим в тех случаях, когда известно, что запрос вернет одну строку.

cursor.fetchone() получает только следующую строку из результата. Если же строк нет, то возвращается None. Пример:


import sqlite3

def read_single_row(developer_id):
try:
sqlite_connection = sqlite3.connect('sqlite_python.db')
cursor = sqlite_connection.cursor()
print("Подключен к SQLite")

sqlite_select_query = """SELECT * from sqlitedb_developers where id = ?"""
cursor.execute(sqlite_select_query, (developer_id, ))
print("Чтение одной строки \n")
record = cursor.fetchone()
print("ID:", record[0])
print("Имя:", record[1])
print("Почта:", record[2])
print("Добавлен:", record[3])
print("Зарплата:", record[4])

cursor.close()

except sqlite3.Error as error:
print("Ошибка при работе с SQLite", error)
finally:
if sqlite_connection:
sqlite_connection.close()
print("Соединение с SQLite закрыто")

read_single_row(3)

Вывод:

Подключен к SQLite
Чтение одной строки 

ID: 3
Имя: Valentin
Почта: exp3@gmail.com
Добавлен: 2020-11-23
Зарплата: 6500.0
Соединение с SQLite закрыто
]]>
Вставка данных в таблицу SQLite https://pythonru.com/biblioteki/vstavka-dannyh-v-tablicu-sqlite-v-python Sun, 29 Nov 2020 13:58:13 +0000 https://pythonru.com/?p=4074 В этом материале рассматривается, как выполнять операцию Insert в SQLite из Python для добавления новых строк в таблицу:

  • Добавление одной или нескольких строк в таблицу SQLite.
  • Добавление целых чисел, строк, чисел с плавающей точкой, с двойной точностью, а также значений datetime в таблицу SQLite.
  • Использование запросов с параметрами для добавления переменных Python в качестве динамических данных в таблицу.

Перед выполнением следующих программ нужно убедиться, что вам известны название таблицы, а также информация о ее колонках. В этом примере будет использоваться таблица sqlitedb_developers.

Эта таблица была создана в первой части руководства по sqlite3.

Пример вставки строки в таблицу SQLite

Сейчас таблица sqlitedb_developers пустая, и ее нужно заполнить. Для этого необходимо выполнить следующие шаги:

  • Установить SQLite-соединение из Python.
  • Создать объект Cursor с помощью объекта соединения.
  • Создать INSERT-запрос. Для этого нужно знать таблицу и подробности о колонках.
  • Выполнить запрос с помощью cursor.execute().
  • После успешного завершения нужно не забыть выполнить коммит изменений в базу данных.
  • Также важно не забыть перехватить исключения SQLite.
  • Наконец, следует проверить результат, вернув данные из таблицы.

Посмотрим на программу:


import sqlite3

try:
sqlite_connection = sqlite3.connect('sqlite_python.db')
cursor = sqlite_connection.cursor()
print("Подключен к SQLite")

sqlite_insert_query = """INSERT INTO sqlitedb_developers
(id, name, email, joining_date, salary)
VALUES
(1, 'Oleg', 'oleg04@gmail.com', '2020-11-29', 8100);"""
count = cursor.execute(sqlite_insert_query)
sqlite_connection.commit()
print("Запись успешно вставлена ​​в таблицу sqlitedb_developers ", cursor.rowcount)
cursor.close()

except sqlite3.Error as error:
print("Ошибка при работе с SQLite", error)
finally:
if sqlite_connection:
sqlite_connection.close()
print("Соединение с SQLite закрыто")

Вывод:

Подключен к SQLite
Запись успешно вставлена ​​в таблицу sqlitedb_developers  1
Соединение с SQLite закрыто

Теперь можно проверить результат, посмотрев таблицу через программу DB Browser.

Пример вставки строки в таблицу SQLite

Разбор кода

  1. import sqlite3:
    • На этой строке модуль sqlite3 импортируется в программу.
    • С помощью классов и методов из модуля можно взаимодействовать с базой данных SQLite.
  2. sqlite3.connect() и connection.cursor():
    • С помощью метода sqlite3.connect() устанавливается соединение с базой данных SQLite из Python.
    • Дальше используется connection.cursor() для получения объекта cursor из объекта соединения.
  3. После этого готовится INSERT-запрос для вставки данных в таблицу. В нем указываются названия колонок и их значения. Всего в таблице 5 колонок.
  4. cursor.execute():
    • С помощью метода execute() объекта сursor выполняется запрос INSERT.
    • Чтобы сохранить изменения в базе, нужно использовать connection.commit().
    • А с помощью cursor.rowcount можно узнать количество отредактированных строк.

И в блоке finally после завершения операции закрываются объекты cursor и соединение.

Использование переменных в запросе INSERT

Иногда в колонку таблицы нужно вставить значение переменной Python. Этой переменной может быть что угодно: целое число, строка, число с плавающей точкой, datetime. Например, при регистрации пользователь вводит свои данные. Их и можно взять вставить в таблицу SQLite.

Для этого есть запрос с параметрами. Он позволяет использовать переменные Python на месте заполнителей (?) в запросе. Пример:


import sqlite3

def insert_varible_into_table(dev_id, name, email, join_date, salary):
try:
sqlite_connection = sqlite3.connect('sqlite_python.db')
cursor = sqlite_connection.cursor()
print("Подключен к SQLite")

sqlite_insert_with_param = """INSERT INTO sqlitedb_developers
(id, name, email, joining_date, salary)
VALUES (?, ?, ?, ?, ?);"""

data_tuple = (dev_id, name, email, join_date, salary)
cursor.execute(sqlite_insert_with_param, data_tuple)
sqlite_connection.commit()
print("Переменные Python успешно вставлены в таблицу sqlitedb_developers")

cursor.close()

except sqlite3.Error as error:
print("Ошибка при работе с SQLite", error)
finally:
if sqlite_connection:
sqlite_connection.close()
print("Соединение с SQLite закрыто")

insert_varible_into_table(2, 'Viktoria', 's_dom34@gmail.com', '2020-11-19', 6000)
insert_varible_into_table(3, 'Valentin', 'exp3@gmail.com', '2020-11-23', 6500)

Вывод: таблица sqlitedb_developers после вставки переменной Python в качестве значения колонки.

Подключен к SQLite
Переменные Python успешно вставлены в таблицу sqlitedb_developers
Соединение с SQLite закрыто
Подключен к SQLite
Переменные Python успешно вставлены в таблицу sqlitedb_developers
Соединение с SQLite закрыто

Проверить результат можно, получив данные из таблицы.

Использование переменных в запросе INSERT

Вставка нескольких строк с помощью executemany()

В предыдущем примере для вставки одной записи в таблицу использовался метод execute() объекта cursor, но иногда требуется вставить несколько строчек.

Например, при чтении файла, например, CSV, может потребоваться добавить все записи из него в таблицу SQLite. Вместе выполнения запроса INSERT для каждой записи, можно выполнить все операции в один запрос. Добавить несколько записей в таблицу SQLite можно с помощью метода executemany() объекта cursor.

Этот метод принимает два аргумента: запрос SQL и список записей.


import sqlite3

def insert_multiple_records(records):
try:
sqlite_connection = sqlite3.connect('sqlite_python.db')
cursor = sqlite_connection.cursor()
print("Подключен к SQLite")

sqlite_insert_query = """INSERT INTO sqlitedb_developers
(id, name, email, joining_date, salary)
VALUES (?, ?, ?, ?, ?);"""

cursor.executemany(sqlite_insert_query, records)
sqlite_connection.commit()
print("Записи успешно вставлены в таблицу sqlitedb_developers", cursor.rowcount)
sqlite_connection.commit()
cursor.close()

except sqlite3.Error as error:
print("Ошибка при работе с SQLite", error)
finally:
if sqlite_connection:
sqlite_connection.close()
print("Соединение с SQLite закрыто")

records_to_insert = [(4, 'Jaroslav', 'idebylos@gmail.com', '2020-11-14', 8500),
(5, 'Timofei', 'ullegyddomm@gmail.com', '2020-11-15',6600),
(6, 'Nikita', 'aqillysso@gmail.com', '2020-11-27', 7400)]

insert_multiple_records(records_to_insert)

Снова проверка с помощью получения данных из таблицы.

Подключен к SQLite
Записи успешно вставлены в таблицу sqlitedb_developers 3
Соединение с SQLite закрыто
Вставка нескольких строк с помощью executemany()

Разберем последний пример:

  • После подключения к базе данных подготавливается список записей для вставки в таблицу. Каждая из них — это всего лишь строка.
  • Инструкция SQLite INSERT содержит запрос с параметрами, где на месте каждого значения стоит вопросительный знак.
  • Дальше с помощью cursor.executemany(sqlite_insert_query, recordList) в таблицу вставляются несколько записей.
  • Чтобы узнать количество вставленных строк используется метод cursor.rowcount. Наконец, нужно не забыть сохранить изменения в базе.
]]>
Введение в SQLite Python https://pythonru.com/biblioteki/vvedenie-v-sqlite-python Sun, 22 Nov 2020 14:24:20 +0000 https://pythonru.com/?p=4028 Цель этого руководства — продемонстрировать принципы разработки приложений на Python с использованием базы данных SQLite.

Подключение к SQLite в Python

В этом разделе разберем, как создавать базу данных SQLite и подключаться к ней в Python с помощью модуля sqlite3.

Для установки соединения нужно указать название базы данных, к которой требуется подключиться. Если указать название той, что уже есть на диске, то произойдет подключение. Если же указать другое, то SQLite создаст новую базу данных.

Для подключения к SQLite нужно выполнить следующие шаги

  • Использовать метод connect() из модуля sqlite3 и передать в качестве аргумента название базы данных.
  • Создать объект cursor с помощью объекта соединения, который вернул прошлый метод для выполнения SQLite-запросов из Python.
  • Закрыть объект cursor после завершения работы.
  • Перехватить исключение базы данных, если в процессе подключения произошла ошибка.

Следующая программа создает файл базы данных sqlite_python.db и выводит подробности о версии SQLite.


import sqlite3

try:
sqlite_connection = sqlite3.connect('sqlite_python.db')
cursor = sqlite_connection.cursor()
print("База данных создана и успешно подключена к SQLite")

sqlite_select_query = "select sqlite_version();"
cursor.execute(sqlite_select_query)
record = cursor.fetchall()
print("Версия базы данных SQLite: ", record)
cursor.close()

except sqlite3.Error as error:
print("Ошибка при подключении к sqlite", error)
finally:
if (sqlite_connection):
sqlite_connection.close()
print("Соединение с SQLite закрыто")

После подключения должно появиться следующее сообщение.

База данных создана и успешно подключена к SQLite
Версия базы данных SQLite:  [('3.31.1',)]
Соединение с SQLite закрыто

Понимание SQLite-подключения в подробностях

import sqlite3

  • Эта строка импортирует в программу модуль sqlite3. С помощью классов и методов из этого модуля можно взаимодействовать с базой данных SQLite.

sqlite3.connect()

  • С помощью метода connect() выполняется подключение к базе данных. Этот метод возвращает объект подключения SQLite.
  • Объект connection не является потокобезопасным. Модуль sqlite3 не позволяет делиться подключением между потоками. Если попытаться сделать это, то можно получить исключение.
  • Метод connect() принимает разные аргументы. В этом примере передается название базы данных.

cursor=sqliteConnection.cursor()

  • С помощью объекта соединения создается объект cursor, который позволяет выполнять SQLite-запросы из Python.
  • Для одного соединения можно создать неограниченное количество cursor. Он также не является потокобезопасным. Модуль не позволяет делиться объектами cursor между потоками. Если это сделать, то будет ошибка.

После этого создается запрос для получения версии базы данных.

cursor.execute()

  • С помощью метода execute объекта cursor можно выполнить запрос в базу данных из Python. Он принимает SQLite-запрос в качестве параметра и возвращает resultSet — то есть, строки базы данных
  • Получить результат запроса из resultSet можно с помощью методов, например, fetchAll()
  • В этом примере SELECT version(); выполняется для получения версии базы данных SQLite.

Блок try-except-finally: весь код расположен в блоке try-except, что позволит перехватить исключения и ошибки базы данных, которые могут появиться в процессе.

  • С помощью класса sqlite3.Error можно обработать любую ошибку и исключение, которые могут появиться при работе с SQLite из Python.
  • Это позволит сделать приложение более отказоустойчивым. Класс sqlite3.Error позволит понять суть ошибки. Он возвращает сообщение и код ошибки.

cursor.close() и connection.close()

  • Хорошей практикой считается закрывать объекты connection и curosor после завершения работы, чтобы избежать проблем с базой данных.

Создание таблицы SQLite в Python

В этом разделе разберемся, как создавать таблицы в базе данных SQLite с помощью Python и модуля sqlite3. Создание таблицы — это DDL-запрос, выполняемый из Python.

В этом примере создадим базу sqlitedb_developers в базе данных sqlite_python.db.

Шаги для создания таблицы в SQLite с помощью Python:

  • Соединиться с базой данных с помощью sqlite3.connect(). Речь об этом шла в первом разделе.
  • Подготовить запрос создания таблицы.
  • Выполнить запрос с помощью cursor.execute(query).
  • Закрыть соединение с базой и объектом cursor.

import sqlite3

try:
sqlite_connection = sqlite3.connect('sqlite_python.db')
sqlite_create_table_query = '''CREATE TABLE sqlitedb_developers (
id INTEGER PRIMARY KEY,
name TEXT NOT NULL,
email text NOT NULL UNIQUE,
joining_date datetime,
salary REAL NOT NULL);'''

cursor = sqlite_connection.cursor()
print("База данных подключена к SQLite")
cursor.execute(sqlite_create_table_query)
sqlite_connection.commit()
print("Таблица SQLite создана")

cursor.close()

except sqlite3.Error as error:
print("Ошибка при подключении к sqlite", error)
finally:
if (sqlite_connection):
sqlite_connection.close()
print("Соединение с SQLite закрыто")
База данных подключена к SQLite
Таблица SQLite создана
Соединение с SQLite закрыто
Создание таблицы SQLite в Python

Типы данных SQLite и соответствие типам Python

Перед переходом к выполнению CRUD-операций в SQLite из Python сначала нужно разобраться с типами данных SQLite и соответствующими им типами данных в Python, которые помогают хранить и считывать данные из таблицы.

У движка SQLite есть несколько классов для хранения значений. Каждое значение, хранящееся в базе данных, имеет один из следующих типов или классов.

Типы данных SQLite:

  • NULL — значение NULL
  • INTEGER — числовые значения. Целые числа хранятся в 1, 2, 3, 4, 6 и 8 байтах в зависимости от величины
  • REAL — числа с плавающей точкой, например, 3.14, число Пи
  • TEXT — текстовые значения. Могут храниться в кодировке UTF-8, UTF-16BE или UTF-16LE
  • BLOB — бинарные данные. Для хранения изображений и файлов

Следующие типы данных из Python без проблем конвертируются в SQLite. Для конвертации достаточно лишь запомнить эту таблицу.

Тип PythonТип SQLite
NoneNULL
intINTEGER
floatREAL
strTEXT
bytesBLOB

Выполнение SQL запросов с помощью функции executescript

Скрипты SQLite отлично справляются со стандартными задачами. Это набор SQL-команд, сохраненных в файле (в формате .sql). Один файл содержит одну или больше SQL-операций, которые затем выполняются из командной строки.

Дальше несколько распространенных сценариев использования SQL-скриптов

  • Создание резервных копий сразу нескольких баз данных за раз.
  • Сравнение количества строк двух разных баз с одной схемой.
  • Создание всех таблиц в одном скрипте, что позволит создать нужную схему на любом сервере

Выполнить скрипт из командной строки SQLite можно с помощью команды .read:

sqlite> .read sqlitescript.sql

Например, этот простой скрипт создает две таблицы.

CREATE TABLE fruits (
 id INTEGER PRIMARY KEY,
 name TEXT NOT NULL,
 price REAL NOT NULL
);

CREATE TABLE drinks (
 id INTEGER PRIMARY KEY,
 name TEXT NOT NULL,
 price REAL NOT NULL
);

Теперь посмотрим, как выполнить его из Python.


import sqlite3

try:
sqlite_connection = sqlite3.connect('sqlite_python.db')
cursor = sqlite_connection.cursor()
print("База данных подключена к SQLite")

with open('sqlite_create_tables.sql', 'r') as sqlite_file:
sql_script = sqlite_file.read()

cursor.executescript(sql_script)
print("Скрипт SQLite успешно выполнен")
cursor.close()

except sqlite3.Error as error:
print("Ошибка при подключении к sqlite", error)
finally:
if (sqlite_connection):
sqlite_connection.close()
print("Соединение с SQLite закрыто")
Выполнение SQL запросов с помощью функции executescript

Таблицы SQLite создаются за счет выполнения скрипта из Python. Вывод:

База данных подключена к SQLite
Скрипт SQLite успешно выполнен
Соединение с SQLite закрыто

Примечание: после соединения с SQLite все содержимое файла сохраняется в переменной. Затем используется команда cursor.executescript(script) для выполнения всех инструкций за раз.

Исключения базы данных SQLite

  • sqlite3.Warning. Подкласс Exception. Его можно игнорировать, если нужно, чтобы оно не останавливало выполнение.
  • sqlite3.Error. Базовый класс для остальных исключений модуля sqlite3. Подкласс Exception.
  • sqlite3.DatabaseError. Исключение, которое возвращается при ошибках базы данных. Например, если попытаться открыть файл как базу sqite3, хотя он ею не является, то вернется ошибка «sqlite3.DatabaseError: file is encrypted or is not a database».
  • sqlite3.IntegrityError. Подкласс DatabaseError. Эта ошибка возвращается, когда затрагиваются отношения в базе, например, например, не проходит проверка внешнего ключа.
  • sqlite3.ProgrammingError. Подкласс DatabaseError. Эта ошибка возникает из-за ошибок программиста: создание таблицы с именем, которое уже занято, синтаксическая ошибка в SQL-запросах.
  • sqlite3.OperationalError. Подкласс DatabaseError. Эту ошибку невозможно контролировать. Она появляется в ситуациях, которые касаются работы базы данных, например, обрыв соединения, неработающий сервер, проблемы с источником данных и так далее.
  • sqlite3.NotSupportedError. Это исключение появляется при попытке использовать неподдерживаемое базой данных API. Пример: вызов метода rollback() для соединения, которое не поддерживает транзакции. Вызов коммита после команды создания таблицы.

Таким образом рекомендуется всегда писать код управления базой данных в блоке try, чтобы была возможность перехватывать исключения и предпринимать действия, которые помогут справиться с ними.

Например, попробуем добавить данные в таблицу, которой не существует и выведем весь стек исключений из Python.


import sqlite3
import traceback
import sys

try:
sqlite_connection = sqlite3.connect('sqlite_python.db')
cursor = sqlite_connection.cursor()
print("База данных подключена к SQLite")

sqlite_insert_query = """INSERT INTO unknown_table_1
(id, text) VALUES (1, 'Демо текст')"""

count = cursor.execute(sqlite_insert_query)
sqlite_connection.commit()
print("Запись успешно вставлена ​​в таблицу sqlitedb_developers ", cursor.rowcount)
cursor.close()

except sqlite3.Error as error:
print("Не удалось вставить данные в таблицу sqlite")
print("Класс исключения: ", error.__class__)
print("Исключение", error.args)
print("Печать подробноcтей исключения SQLite: ")
exc_type, exc_value, exc_tb = sys.exc_info()
print(traceback.format_exception(exc_type, exc_value, exc_tb))
finally:
if (sqlite_connection):
sqlite_connection.close()
print("Соединение с SQLite закрыто")
База данных подключена к SQLite
Не удалось вставить данные в таблицу sqlite
Класс исключения:  <class 'sqlite3.OperationalError'>
Исключение ('no such table: unknown_table_1',)
Печать подробноcтей исключения SQLite: 
['Traceback (most recent call last):\n', '  File "C:\\Users\\demo\\AppData\\Local\\Programs\\Python\\Python38\\sqlitet.py", line 13, in <module>\n    count = cursor.execute(sqlite_insert_query)\n', 'sqlite3.OperationalError: no such table: unknown_table_1\n']
Соединение с SQLite закрыто

Изменения timeout при подключении из Python

Бывает такое, что есть несколько подключений к базе данных SQLite, и одно из них выполняет определенное изменение. Для этого соединению требуется выполнить блокировку — база данных блокируется до тех пор, пока транзакция не будет завершена.

Параметр timeout, который задается при подключении, определяет, как долго соединение будет ожидать отключения блокировки перед возвращением исключения.

По умолчанию значение этого параметра равно 5.0 (5 секунд). Его не нужно задавать, потому что это значение по умолчанию. Таким образом при подключении к базе данных из Python, если ответ не будет получен в течение 5 секунд, вернется исключение. Однако параметр все-таки можно задать в функции sqlite3.connect.

Посмотрим, как это сделать из Python.


import sqlite3

def read_sqlite_table():
try:
sqlite_connection= sqlite3.connect('sqlite_python.db', timeout=20)
cursor = sqlite_connection.cursor()
print("Подключен к SQLite")

sqlite_select_query = """SELECT count(*) from sqlitedb_developers"""
cursor.execute(sqlite_select_query)
total_rows = cursor.fetchone()
print("Всего строк: ", total_rows)
cursor.close()

except sqlite3.Error as error:
print("Ошибка при подключении к sqlite", error)
finally:
if (sqlite_connection):
sqlite_connection.close()
print("Соединение с SQLite закрыто")

read_sqlite_table()

Вывод:

Подключен к SQLite
Всего строк:   (0,)
Соединение с SQLite закрыто

Получение изменений с момента подключения к базе данных

Для статистики может потребоваться найти количество строк базы данных, которые были вставлены, удалены или изменены с момента открытия соединения. Для этого используется функция connection.total_changes модуля sqlite3.

Этот метод возвращается общее количество строк, которые были затронуты. Рассмотрим пример.


import sqlite3

try:
sqlite_connection = sqlite3.connect('sqlite_python.db')
cursor = sqlite_connection.cursor()
print("Подключен к SQLite")

sqlite_insert_query = """INSERT INTO sqlitedb_developers
(id, name, email, joining_date, salary)
VALUES (4, 'Alex', 'sale@gmail.com', '2020-11-20', 8600);"""
cursor.execute(sqlite_insert_query)

sql_update_query = """Update sqlitedb_developers set salary = 10000 where id = 4"""
cursor.execute(sql_update_query)

sql_delete_query = """DELETE from sqlitedb_developers where id = 4"""
cursor.execute(sql_delete_query)

sqlite_connection.commit()
cursor.close()

except sqlite3.Error as error:
print("Ошибка при работе с SQLite", error)
finally:
if (sqlite_connection):
print("Всего строк, измененных после подключения к базе данных: ", sqlite_connection.total_changes)
sqlite_connection.close()
print("Соединение с SQLite закрыто")
Подключен к SQLite
Всего строк, измененных после подключения к базе данных:  3
Соединение с SQLite закрыто

Сохранение резервной копии базы данных из Python

Модуль sqlite3 в Python предоставляет функцию для сохранения резервной копии базы данных SQLite. С помощью метода connection.backup() можно сделать резервную копию базы SQLite.

connection.backup(target, *, pages=0, progress=None, name="main", sleep=0.250)

Эта функция делает полную резервную копию базы данных SQLite. Изменения записываются в аргумент target, который должен быть экземпляром другого соединения.

По умолчанию когда параметр pages равен 0 или отрицательному числу, вся база данных копируется в один шаг. В противном случае метод выполняет цикл, копируя заданное количество страниц за раз.

Аргумент name определяет базу данных, резервную копию которой нужно сделать. Аргумент sleep — количество секунд между последовательными попытками сохранить оставшиеся страницы. Аргумент sleep можно задать как в качестве целого числа, так и в виде числа с плавающей точкой.

Рассмотрим один пример копирования базы данных в другую.


import sqlite3

def progress(status, remaining, total):
print(f'Скопировано {total-remaining} из {total}...')

try:
sqlite_con = sqlite3.connect('sqlite_python.db')
backup_con = sqlite3.connect('sqlite_backup.db')
with backup_con:
sqlite_con.backup(backup_con, pages=3, progress=progress)
print("Резервное копирование выполнено успешно")
except sqlite3.Error as error:
print("Ошибка при резервном копировании: ", error)
finally:
if(backup_con):
backup_con.close()
sqlite_con.close()
Скопировано 3 из 5...
Скопировано 5 из 5...
Резервное копирование выполнено успешно

Примечания:

  • После подключения к SQLite обе базы данных были открыты с помощью двух разных подключений
  • Дальше выполняется метод connection.backup() с помощью экземпляра первого подключения. Также задано количество страниц, которые нужно скопировать за одну итерацию.
]]>