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

205 投票
5 回答
108391 浏览
提问于 2025-04-16 19:22

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

5 个回答

58

12.6.8. 高效使用sqlite3

12.6.8.1. 使用快捷方法

通过使用连接对象的非标准方法 execute()executemany()executescript(),你的代码可以写得更简洁,因为你不需要明确地创建那些通常是多余的光标对象(Cursor)。相反,光标对象会被隐式创建,这些快捷方法会返回光标对象。这样,你可以直接在连接对象上执行一个SELECT语句,并直接遍历结果,只需一次调用。

(sqlite3 文档; 强调是我的.)

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

因为连接对象的方法是非标准的,也就是说,它们不属于Python数据库API规范v2.0(PEP 249)。

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

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

不过,如果你确定不会切换数据库,我觉得使用 connection.execute 的快捷方式也是完全可以的,这样可以更“高效”。

67

根据官方的文档connection.execute() 是一个非标准的快捷方式,它会创建一个中间的游标对象:

Connection.execute
这是一个非标准的快捷方式,它通过调用cursor()方法来创建一个游标对象,然后用给定的参数调用这个游标的execute()方法,并返回这个游标。

94

我觉得这只是一个不太恰当的抽象。数据库游标是一种抽象概念,主要用于遍历数据集。

根据维基百科上的相关内容

在计算机科学和技术中,数据库游标是一种控制结构,可以让我们在数据库中的记录之间进行遍历。游标不仅可以帮助我们在遍历时处理数据,比如获取、添加和删除数据库记录。游标的遍历特性使得它与编程语言中的迭代器概念相似。

还有:

游标不仅可以用来从数据库管理系统(DBMS)中获取数据,还可以用来定位表中的某一行,以便进行更新或删除。SQL:2003标准定义了用于这个目的的定位更新和定位删除的SQL语句。这些语句不使用常规的WHERE子句,而是通过游标来识别行。游标必须先打开,并通过FETCH语句定位到某一行。

如果你查看Python sqlite模块的文档,你会发现即使是执行CREATE TABLE语句,也需要一个Python模块cursor,这就意味着在一些情况下,仅仅使用connection对象就足够了——正如提问者所指出的那样。这种抽象与人们理解的数据库游标有所不同,因此用户会感到困惑和沮丧。不管效率如何,这只是一个概念上的负担。如果文档中能指出Python模块cursor与SQL和数据库中的游标有些不同,那就更好了。

撰写回答