- методы fetchall, fetchmany, fetchone, iterdump
- Хранение изображений в БД
- Создание бэкапа БД
- Создание БД в памяти
- Видео по теме
- Получение результатов запроса¶
- Метод fetchone¶
- Метод fetchmany¶
- Метод fetchall¶
- Python: Работа с базой данных, часть 1/2: Используем DB-API
- Готовим инвентарь для дальнейшей комфортной работы
- Python DB-API модули в зависимости от базы данных
- Соединение с базой, получение курсора
- Чтение из базы
- Запись в базу
- Разбиваем запрос на несколько строк в тройных кавычках
- Объединяем запросы к базе данных в один вызов метода
- Делаем подстановку значения в запрос
- Делаем множественную вставку строк проходя по коллекции с помощью метода курсора .executemany()
- Получаем результаты по одному, используя метод курсора .fetchone()
- Курсор как итератор
- UPD: Повышаем устойчивость кода
- UPD: Использование with в psycopg2
- UPD: Ипользование row_factory
- Дополнительные материалы (на английском)
- How to Iterate through cur.fetchall() in Python
- 5 Answers 5
методы fetchall, fetchmany, fetchone, iterdump
Продолжим изучение API для работы с SQLite на языке Python и пару слов о способе извлечения данных из запросов. Об этом мы уже говорили на одном из предыдущих занятий, когда рассматривали методы:
- fetchall() – возвращает число записей в виде упорядоченного списка;
- fetchmany(size) – возвращает число записей не более size;
- fetchone() – возвращает первую запись.
Ссылку на это занятие вы найдете в описании под этим видео (https://youtu.be/fYGfBpuFu0A). Я здесь лишь напомню порядок применения этим функций. Для начала наполним БД cars записями:
И, затем, выполним запрос на выборку записей:
Чтобы в программе на Python получить доступ к сформированной выборке, как раз и нужно воспользоваться функциями:
fetchall, fetchmany или fetchone
В консоли увидим список из кортежей с данными записей в соответствии с указанными полями model и price:
[(‘Audi’, 52642), (‘Mercedes’, 57127), (‘Skoda’, 9000), (‘Volvo’, 29000), (‘Bentley’, 350000)]
По аналогии для fetchone:
будет взята только первая запись. И для fetchmany:
берем не более четырех первых записей:
[(‘Audi’, 52642), (‘Mercedes’, 57127), (‘Skoda’, 9000), (‘Volvo’, 29000)]
Наконец, мы говорили, что после формирования выборки сам экземпляр класса Cursor можно использовать как итерируемый объект и выбирать записи в цикле:
Преимущество такого подхода в экономии памяти при большом числе записей в выборке. Здесь на каждой итерации цикла мы выбираем только одну следующую запись, а не храним их сразу целиком в памяти в виде списка. Это часто бывает эффективно и очень удобно.
Далее, иногда более предпочтительным вариантом выходных данных является не кортеж с данными, а словарь, позволяющий обращаться к элементам по именам полей. Для этого после установления соединения с БД следует прописать вот такую строчку:
Теперь, при выполнении программы увидим, что переменная result в цикле ссылается на объект Row, а не кортеж:
И через этот объект доступ к данным осуществляется с помощью имен полей таблицы cars:
Хранение изображений в БД
Часто в БД требуется хранить небольшие изображения, например, аватары пользователей. Для этого имеется специальный тип данных BLOB. Давайте создадим таблицу users с полем ava:
Далее напишем вспомогательную функцию считывания изображения из файла:
Если изображение было успешно прочитано, то функция возвратит набор двоичных данных, иначе значение False. Затем, в менеджере контекста БД вызовем ее и при успешном чтении данных записываем в таблицу users:
Обратите внимание, прежде чем бинарные данные передавать в поле BLOB их нужно закодировать в бинарный объект модуля SQLite. Для этого и вызывается метод Binary, которому передается последовательность прочитанных байт изображения.
Запустим программу и перейдем в приложение DB Browser. Откроем там таблицу users. И при выборе поля BLOB справа увидим изображение, которое там хранится:
Давайте теперь прочитаем изображение из этого поля. Выполним следующий запрос:
и с помощью метода fetchone обратимся к первой (и единственной) записи и возьмем данные из поля ava:
Чтобы нам знать, что изображение было успешно прочитано, сохраним его в файл. Для этого запишем вот такую функцию:
У нас в рабочем каталоге программы появился файл out.png и при его просмотре видим, что это то самое изображение. Вот так производится запись и чтение бинарных данных в SQLite.
Создание бэкапа БД
Класс Cursor содержит один весьма полезный метод
возвращающий итератор для SQL-запросов, на основе которых можно воссоздать текущую БД. Если просто вывести в консоль возвращаемых строк:
То получим список следующих SQL-команд:
С помощью этих запросов можно точно воссоздать таблицы БД, то есть, их можно рассматривать как некий дамп БД.
Чтобы наша программа выглядела более функциональной, сохраним все эти строчки в отдельном файле:
После запуска в рабочем каталоге программы появится файл sql_damp.sql с набором соответствующих команд.
Теперь, чтобы восстановить БД с помощью этого файла можно воспользоваться методом executescript, о котором мы уже говорили:
Перед выполнением этой программы удалим файл cars.db и после запуска снова увидим этот файл с прежним содержимым.
Создание БД в памяти
Интересной особенностью модуля SQLite является возможность создания БД непосредственно в памяти. Такая организация позволяет хранить временные данные программы в формате таблиц и работать с ними через SQL-запросы. В ряде случаев это бывает весьма удобно.
Для создания БД в памяти устройства подключение записывается в виде:
Мы здесь создали подключение, указав специальный параметр «:memory:», что означает «память» и, затем, в менеджере контекста создали таблицу dict с двумя полями, заполнили ее значениями и сделали выборку всех английских слов, начинающихся с первой буквы ‘c’.
Этот пример показывает как можно использовать богатые возможности СУБД для хранения и выборки данных в процессе работы приложения, не создавая на диске БД.
На этом мы завершим цикл занятий по SQLite. Данного материала вам вполне хватит для большинства приложений. Ну а по мере его использования неминуемо узнаете многие другие нюансы работы данного модуля.
Видео по теме
Python SQLite #1: что такое СУБД и реляционные БД
Python SQLite #2: подключение к БД, создание и удаление таблиц
Python SQLite #3: команды SELECT и INSERT при работе с таблицами БД
Python SQLite #4: команды UPDATE и DELETE при работе с таблицами
Python SQLite #5: агрегирование и группировка GROUP BY
Python SQLite #6: оператор JOIN для формирования сводного отчета
Python SQLite #7: оператор UNION объединения нескольких таблиц
Python SQLite #8: вложенные SQL-запросы
Python SQLite #9: методы execute, executemany, executescript, commit, rollback и свойство lastrowid
Python SQLite #10: методы fetchall, fetchmany, fetchone, Binary, iterdump
© 2021 Частичное или полное копирование информации с данного сайта для распространения на других ресурсах, в том числе и бумажных, строго запрещено. Все тексты и изображения являются собственностью сайта
Источник
Получение результатов запроса¶
Для получения результатов запроса в sqlite3 есть несколько способов:
- использование методов fetch — в зависимости от метода возвращаются одна, несколько или все строки
- использование курсора как итератора — возвращается итератор
Метод fetchone¶
Метод fetchone возвращает одну строку данных.
Пример получения информации из базы данных sw_inventory.db:
Обратите внимание, что хотя запрос SQL подразумевает, что запрашивалось всё содержимое таблицы, метод fetchone вернул только одну строку.
Если повторно вызвать метод, он вернет следующую строку:
Аналогичным образом метод будет возвращать следующие строки. После обработки всех строк метод начинает возвращать None.
За счет этого метод можно использовать в цикле, например, так:
Метод fetchmany¶
Метод fetchmany возвращает список строк данных.
С помощью параметра size можно указывать, какое количество строк возвращается. По умолчанию параметр size равен значению cursor.arraysize:
Например, таким образом можно возвращать по три строки из запроса:
Метод выдает нужное количество строк, а если строк осталось меньше, чем параметр size, то оставшиеся строки.
Метод fetchall¶
Метод fetchall возвращает все строки в виде списка:
Важный аспект работы метода — он возвращает все оставшиеся строки.
То есть, если до метода fetchall использовался, например, метод fetchone, то метод fetchall вернет оставшиеся строки запроса:
Метод fetchmany в этом аспекте работает аналогично.
Источник
Python: Работа с базой данных, часть 1/2: Используем DB-API
В статье рассмотрены основные методы DB-API, позволяющие полноценно работать с базой данных. Полный список можете найти по ссылкам в конец статьи.
Требуемый уровень подготовки: базовое понимание синтаксиса SQL и Python.
Готовим инвентарь для дальнейшей комфортной работы
- Python имеет встроенную поддержку SQLite базы данных, для этого вам не надо ничего дополнительно устанавливать, достаточно в скрипте указать импорт стандартной библиотеки
Скачаем тестовую базу данных, с которой будем работать. В данной статье будет использоваться открытая (MIT лицензия) тестовая база данных “Chinook”. Скачать ее можно с репозитория:
Для удобства работы с базой (просмотр, редактирование) нам нужна программа браузер баз данных, поддерживающая SQLite. В статье работа с браузером не рассматривается, но он поможет Вам наглядно видеть что происходит с базой в процессе наших экспериментов.
Примечание: внося изменения в базу не забудьте их применить, так как база с непримененными изменениями остается залоченной.
Вы можете использовать (последние два варианта кросс-платформенные и бесплатные):
Python DB-API модули в зависимости от базы данных
| База данных | DB-API модуль |
|---|---|
| SQLite | sqlite3 |
| PostgreSQL | psycopg2 |
| MySQL | mysql.connector |
| ODBC | pyodbc |
Соединение с базой, получение курсора
Для начала рассмотрим самый базовый шаблон DB-API, который будем использовать во всех дальнейших примерах:
При работе с другими базами данных, используются дополнительные параметры соединения, например для PostrgeSQL:
Чтение из базы
Обратите внимание: После получения результата из курсора, второй раз без повторения самого запроса его получить нельзя — вернется пустой результат!
Запись в базу
Примечание: Если к базе установлено несколько соединений и одно из них осуществляет модификацю базы, то база SQLite залочивается до завершения (метод соединения .commit()) или отмены (метод соединения .rollback()) транзакции.
Разбиваем запрос на несколько строк в тройных кавычках
Длинные запросы можно разбивать на несколько строк в произвольном порядке, если они заключены в тройные кавычки — одинарные (»’…»’) или двойные («»». «»»)
Конечно в таком простом примере разбивка не имеет смысла, но на сложных длинных запросах она может кардинально повышать читаемость кода.
Объединяем запросы к базе данных в один вызов метода
Метод курсора .execute() позволяет делать только один запрос за раз, при попытке сделать несколько через точку с запятой будет ошибка.
Для решения такой задачи можно либо несколько раз вызывать метод курсора .execute()
Либо использовать метод курсора .executescript()
Данный метод также удобен, когда у нас запросы сохранены в отдельной переменной или даже в файле и нам его надо применить такой запрос к базе.
Делаем подстановку значения в запрос
Важно! Никогда, ни при каких условиях, не используйте конкатенацию строк (+) или интерполяцию параметра в строке (%) для передачи переменных в SQL запрос. Такое формирование запроса, при возможности попадания в него пользовательских данных – это ворота для SQL-инъекций!
Правильный способ – использование второго аргумента метода .execute()
Возможны два варианта:
Примечание 1: В PostgreSQL (UPD: и в MySQL) вместо знака ‘?’ для подстановки используется: %s
Примечание 2: Таким способом не получится заменять имена таблиц, одно из возможных решений в таком случае рассматривается тут: stackoverflow.com/questions/3247183/variable-table-name-in-sqlite/3247553#3247553
UPD: Примечание 3: Благодарю Igelko за упоминание параметра paramstyle — он определяет какой именно стиль используется для подстановки переменных в данном модуле.
Вот ссылка с полезным приемом для работы с разными стилями подстановок.
Делаем множественную вставку строк проходя по коллекции с помощью метода курсора .executemany()
Получаем результаты по одному, используя метод курсора .fetchone()
Он всегда возвращает кортеж или None. если запрос пустой.
Важно! Стандартный курсор забирает все данные с сервера сразу, не зависимо от того, используем мы .fetchall() или .fetchone()
Курсор как итератор
UPD: Повышаем устойчивость кода
Благодарю paratagas за ценное дополнение:
Для большей устойчивости программы (особенно при операциях записи) можно оборачивать инструкции обращения к БД в блоки «try-except-else» и использовать встроенный в sqlite3 «родной» объект ошибок, например, так:
UPD: Использование with в psycopg2
Благодарю KurtRotzke за ценное дополнение:
Последние версии psycopg2 позволяют делать так:
Некоторые объекты в Python имеют __enter__ и __exit__ методы, что позволяет «чисто» взаимодействовать с ними, как в примере выше.
UPD: Ипользование row_factory
Благодарю remzalp за ценное дополнение:
Использование row_factory позволяет брать метаданные из запроса и обращаться в итоге к результату, например по имени столбца.
По сути — callback для обработки данных при возврате строки. Да еще и полезнейший cursor.description, где есть всё необходимое.
Пример из документации:
Дополнительные материалы (на английском)
- Краткий бесплатный он-лайн курс — Udacity — Intro to Relational Databases — Рассматриваются синтаксис и принципы работы SQL, Python DB-API – и теория и практика в одном флаконе. Очень рекомендую для начинающих!
Источник
How to Iterate through cur.fetchall() in Python
I am working on database connectivity in Python 3.4. There are two columns in my database.
Below is the query which gives me all the data from two columns in shown format QUERY:
To iterate through this output, my code is as below
This gives me below error
Let me know how can we work on individual values of fetchall()
5 Answers 5
It looks like you have two colunms in the table, so each row will contain two elements.
It is easiest to iterate through them this way:
That is the same as:
You could also, as you tried:
But that failed because you overwrote i with the value of first column, in this line: for i, row in data: .
EDIT
BTW, in general, you will never need this pattern in Python:
Instead of that, it is common to do simply:
To iterate over and print rows from cursor.fetchall() you’ll just want to do:
You should also be able to access indices of the row, such as row[0] , row[1] , iirc.
Of course, instead of printing the row, you can manipulate that row’s data however you need. Imagine the cursor as a set of rows/records (that’s pretty much all it is).
you are taking a strings i and j and indexing it like
which gave you typeError
this is because i in data is a string and your a indexing this
As the output you given [(‘F:\\test1.py’, ‘12345abc’), (‘F:\\test2.py’, ‘avcr123’)]
So you don’t need row[i] or row[j], that was wrong, in that each step of that iteration
is the same as i, row = (‘abc’, ‘def’) it set abc to variable i and ‘def’ to row
BTW ,I don’t know what database you use, if you use Mysql and python driver MySQL Connector , you can checkout this guide to fetch mysql result as dictionary you can get a dict in iteration, and the keys is your table fields’ name. I think this method is convenient more.
Источник