为什么在查询 sqlite 数据库时需要创建游标?

我对 Python 的 sqlite3模块(和一般的 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对象呢?

90560 次浏览

您需要一个光标对象来获取结果。您的示例之所以能够工作,是因为它是一个 INSERT,因此您不会尝试从它返回任何行,但是如果您查看 sqlite3文件,您将注意到连接对象上没有任何 .fetchXXXX方法,所以如果您尝试在没有游标的情况下执行 SELECT,您将无法获得结果数据。

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

根据官方的 医生 connection.execute()是一个创建中间光标对象的 非标准捷径:

连接,执行
这是一个非标准的快捷方式,它通过调用 cursor ()方法创建游标对象,使用给定的参数调用游标的 execute ()方法,并返回游标。

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

来自 维基百科主题文章:

在计算机科学与技术中,数据库光标是一种控件 结构,该结构支持遍历数据库中的记录。 游标有助于随后与 遍历,如数据库的检索、添加和删除 数据库游标的遍历特性使游标 类似于迭代器的编程语言概念。

还有:

游标不仅可以用于将数据从 DBMS 提取到 应用程序,但也可以标识表中要更新的行或 SQL: 2003标准定义了定位更新和 定位删除 SQL 语句 不使用带谓词的常规 WHERE 子句。而是使用游标 标识行。光标必须打开并且已经定位 通过 FETCH 语句在一行上。

如果您检查 Python sqlite 模块上的 docs,您可以看到甚至对于 CREATE TABLE语句也需要一个 python 模块 cursor,因此它用于仅仅一个 connection对象就足够的情况——正如 OP 正确指出的那样。这种抽象不同于人们对数据库光标的理解,因此也不同于用户的困惑和挫折。不管效率如何,这只是一个概念上的开销。如果能在文档中指出 python 模块 cursor与 SQL 和数据库中的游标有所不同,那就太好了。

12.6.8. 使用 sqlite3有效率ly

使用 捷径方法

使用 Connection 对象的 不标准 execute()executemany()executescript()方法,您的代码可以用 更简洁ly 编写,因为您不必显式地创建(通常是 多余的) Cursor 对象。相反,Cursor 对象是隐式创建的,这些快捷方法返回游标对象。这样,您就可以执行一个 SELECT 语句,并只使用 Connection 对象上的一个调用直接对其进行迭代。

(Sqlite3文档; 强调我的。)

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

因为这些连接对象的方法是 不标准,即它们不是 Python 数据库 API 规范 v2.0(PEP 249)的一部分。

只要使用 Cursor 对象的标准方法,就可以确保如果切换到遵循上述规范的另一个数据库实现,代码将是完全可移植的。也许您只需要更改 import线。

但是如果您使用 connection.execute,那么切换就有可能不会那么简单。这就是您可能想要使用 cursor.execute的主要原因。

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

它使我们能够通过到数据库的相同连接拥有多个独立的工作环境。