2011-06-11 543 views
75

我对Python's sqlite3 module(以及有关SQL的总体情况)完全陌生,而且这完全让我失望。对于cursor objects(而不是他们的必要性)的描述的缺乏也很奇怪。为什么在查询sqlite数据库时需要创建一个游标?

的这段代码是做事的首选方式:

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对象?

回答

28

您需要一个游标对象来获取结果。你的例子的工作原理是INSERT,因此你不想从它那里得到任何行,但是如果你看sqlite3 docs,你会注意到在连接对象上没有任何.fetchXXXX方法,所以如果你尝试过没有游标做SELECT,你将无法获得结果数据。

游标对象允许您跟踪哪个结果集是哪个结果集,因为在获取第一个结果之前可以运行多个查询。

+5

另外值得记住:[PEP 249](http://www.python.org/dev/peps/pep-0249/)没有定义'连接对象上execute',这是一个'sqlite3'延期。 – 2011-06-11 19:50:30

+2

它仍然适用于SELECT语句:http://pastebin.com/5ZbhfEn7。原因是您没有在连接对象上调用任何.fetchXXXX方法,所以您正在对由连接的.execute()方法返回的对象调用.fetchXXXX方法。 – 2011-06-12 03:10:18

+0

@杰克:是的,但是你仍然以某种方式结束了游标。 – Amber 2011-06-12 07:15:23

20

根据官方docsconnection.execute()非标准快捷方式创建一个中间游标对象。

41

只是一个错误的抽象在我看来。数据库游标是一种抽象,用于数据集遍历。

Wikipedia article on subject

在计算机科学与技术,数据库光标控制 结构,使穿越了在数据库中的记录。 游标有助于后续处理连同 遍历,如检索,添加和删除数据库 记录。遍历的数据库游标特性使得游标 类似于迭代器的编程语言概念。

和:

光标不仅可以用于从DBMS数据放到一个 应用,而且在确定表中的行更新或删除 。 SQL:2003标准定义了定位更新,并且为此定位了删除SQL语句。 这样的语句不使用带谓词的常规WHERE子句。相反,光标 标识该行。游标必须打开并且已经通过FETCH语句在一行上定位了 。

如果您检查docs on Python sqlite module,你可以看到一个Python模块cursor甚至为CREATE TABLE语句所需,所以它的使用,其中仅connection对象应该足够的情况下 - 如正确地指出由OP。这种抽象与人们对db光标的理解不同,因此也是用户的困惑/沮丧。无论效率如何,这只是一个概念性开销。如果在文档中指出Python模块cursor与SQL和数据库中的游标有点不同,那将会很好。

+3

用于确认(首先)“传统”数据库游标与用于Python中数据库的游标之间的非常混淆的区别 – 2013-03-03 23:58:08

+0

实际上,人们可以明白地[即使不使用游标也可以创建表](https:// xania.org/200711/python-sqlite-gotcha)。 – 2017-07-18 11:07:44

8

12.6.8。中使用sqlite3 高效 LY

12.6.8.1。使用快捷方法

使用Connection对象的非标准​​,executemany()executescript()方法,您可以编写代码更简洁 LY,因为你没有创建(通常多余)游标明确的对象。相反,Cursor对象是隐式创建的,这些快捷方法返回游标对象。这样,您可以执行SELECT语句并直接使用Connection对象上的一次调用直接对其进行迭代。

sqlite3 documentation;重点煤矿。)

为什么不直接使用的连接对象?

由于连接对象的那些方法是nonstandard,即它们不是Python Database API Specification v2.0(PEP 249)的一部分。

只要你使用Cursor对象的标准方法,你可以肯定的是,如果你切换到遵循上述规范的另一个数据库实现,你的代码将完全便携。也许你只需要改变import一行。

但是如果你使用的connection.execute有机会的切换不会是简单的。这是你可能想用cursor.execute代替的主要原因。

但是,如果你确信你不会切换,我会说这是完全可以采取connection.execute快捷方式,是“有效的”。

相关问题