Зачем вам нужно создавать курсор при запросе базы данных sqlite?

133

Я совершенно не знаком с модулем sqlite3 Python (и SQL в целом), и это меня полностью ставит в тупик. Странным также кажется обильное отсутствие описаний cursorпредметов (точнее, их необходимости).

Этот фрагмент кода является предпочтительным способом работы:

import sqlite3
conn = sqlite3.connect("db.sqlite")
c = conn.cursor()
c.execute('''insert into table "users" values ("Jack Bauer", "555-555-5555")''')
conn.commit()
c.close()

Этого нет, хотя он работает так же хорошо и без (казалось бы, бессмысленного) cursor:

import sqlite3
conn = sqlite3.connect("db.sqlite")
conn.execute('''insert into table "users" values ("Jack Bauer", "555-555-5555")''')
conn.commit()

Кто-нибудь может сказать мне, зачем мне нужен cursor?
Это просто кажется бессмысленным. Для каждого метода в моем скрипте, который обращается к базе данных, я должен создать и уничтожить cursor?
Почему бы просто не использовать connectionобъект?

Джек Бауэр
источник

Ответы:

60

Мне кажется, это просто неправильная абстракция. Курсор db - это абстракция, предназначенная для обхода набора данных.

Из статьи в Википедии по теме :

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

И:

Курсоры можно использовать не только для извлечения данных из СУБД в приложение, но и для идентификации строки в таблице, которую необходимо обновить или удалить. Стандарт SQL: 2003 определяет для этой цели операторы SQL с позиционированием обновления и удаления с позиционированием. В таких операторах не используется обычное предложение WHERE с предикатами. Вместо этого курсор определяет строку. Курсор должен быть открыт и уже помещен в строку с помощью оператора FETCH.

Если вы проверите документацию по модулю Python sqlite , вы увидите, что модуль python cursorнеобходим даже для CREATE TABLEоператора, поэтому он используется в тех случаях, когда достаточно простого connectionобъекта - как правильно указано OP. Такая абстракция отличается от того, что люди понимают под курсором db, и, следовательно, вызывает замешательство / разочарование со стороны пользователей. Независимо от эффективности, это просто концептуальные накладные расходы. Было бы неплохо, если бы в документах было указано, что модуль python cursorнемного отличается от того, что есть курсор в SQL и базах данных.

Базель Шишани
источник
7
+1 за признание (поначалу) очень сбивающего с толку различия между "традиционными" курсорами db и курсорами, используемыми для db в Python
Пол Дрейпер
3
Фактически, можно просто создать таблицу даже без использования курсора .
Serge
38

Вам нужен объект курсора для получения результатов. Ваш пример работает, потому что он INSERTи, следовательно, вы не пытаетесь вернуть из него какие-либо строки, но если вы посмотрите sqlite3документы , вы заметите, что нет никаких .fetchXXXXметодов для объектов подключения, поэтому, если вы попытались сделать a SELECTбез курсора у вас не было бы возможности получить результирующие данные.

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

янтарный
источник
5
Также стоит иметь в виду: PEP 249 не определяет executeобъект подключения, это sqlite3расширение.
Cat Plus Plus
4
Он по-прежнему работает с операторами SELECT: pastebin.com/5ZbhfEn7 . Причина в том, что вы не вызываете какие-либо методы .fetchXXXX для объекта соединения, вы вызываете метод .fetchXXXX для объекта, возвращаемого методом .execute () соединения.
Джек Бауэр,
1
Да. Но в одном случае вы получаете (по-видимому) ненужный курсор для запроса базы данных: p
Джек Бауэр
2
Явное использование курсоров - хорошая привычка, поскольку, вероятно, будут будущие проекты, над которыми вы будете работать, без автоматической фиксации.
Эмбер
1
Справедливо. Спасибо за информацию :)
Джек Бауэр
36

Согласно официальной документации connection.execute() , это нестандартный ярлык, который создает промежуточный объект курсора:

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

пользователь
источник
19

12.6.8. Использование sqlite3 эффективного Ly

12.6.8.1. Использование быстрых методов

Используя нестандартные execute() , executemany()и executescript()методы объекта Connection, ваш код может быть написан более кратким LY , потому что вы не должны создавать (часто излишни ) Cursor объекты в явном виде. Вместо этого объекты Cursor создаются неявно, и эти методы быстрого доступа возвращают объекты курсора. Таким образом, вы можете выполнить оператор SELECT и перебрать его напрямую, используя только один вызов объекта Connection.

( документация sqlite3 ; курсив мой.)

Почему бы просто не использовать объект подключения?

Поскольку эти методы объекта подключения нестандартны , то есть они не являются частью спецификации Python Database API версии 2.0 (PEP 249).

Пока вы используете стандартные методы объекта Cursor, вы можете быть уверены, что если вы переключитесь на другую реализацию базы данных, которая соответствует указанной выше спецификации, ваш код будет полностью переносимым. Возможно, вам нужно будет только поменять importстрочку.

Но если вы используете, connection.executeесть шанс, что переключение не будет таким простым. Это основная причина, по которой вы можете захотеть использовать cursor.executeвместо этого.

Однако, если вы уверены, что не собираетесь переключаться, я бы сказал, что вполне нормально использовать connection.executeярлык и действовать «эффективно».

AXO
источник
1

Это дает нам возможность иметь несколько отдельных рабочих сред через одно и то же соединение с базой данных.

Python Learner
источник