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

发布于 2024-11-14 22:05:33 字数 883 浏览 3 评论 0原文

我对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()

这个不是,尽管它工作得同样好并且没有(看似毫无意义的)光标

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

任何人都可以告诉我为什么我需要一个 <代码>光标?
这似乎是毫无意义的开销。对于我的脚本中访问数据库的每个方法,我应该创建和销毁一个游标
为什么不直接使用connection对象呢?

I'm completely new to Python's sqlite3 module (and SQL in general for that matter), and this just completely stumps me. The abundant lack of descriptions of cursor objects (rather, their necessity) also seems odd.

This snippet of code is the preferred way of doing things:

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()

This one isn't, even though it works just as well and without the (seemingly pointless) cursor:

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

Can anyone tell me why I need a cursor?

It just seems like pointless overhead. For every method in my script that accesses a database, I'm supposed to create and destroy a cursor?

Why not just use the connection object?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

秋凉 2024-11-21 22:05:33

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

来自有关主题的维基百科文章

在计算机科学与技术中,数据库游标是一种控件
允许遍历数据库中的记录的结构。
游标方便后续处理与
遍历,例如数据库的检索、添加和删除
记录。数据库游标的遍历特性使得游标
类似于编程语言中的迭代器概念。

和:

游标不仅可以用于将数据从 DBMS 提取到数据库中
应用程序还可以识别表中要更新的行或
已删除。 SQL:2003 标准定义了定位更新和
为此目的定位了删除 SQL 语句。这样的陈述确实
不使用带有谓词的常规 WHERE 子句。相反,一个光标
标识行。光标必须打开并已定位
通过 FETCH 语句在一行上。

如果你检查Python sqlite模块的文档,你可以看到一个python模块即使对于 CREATE TABLE 语句也需要 cursor,因此它用于仅 connection 对象就足够的情况 - 正如OP。这种抽象与人们对数据库游标的理解不同,因此,用户会感到困惑/沮丧。不管效率如何,这只是概念上的开销。如果在文档中指出 python 模块 Cursor 与 SQL 和数据库中的游标有点不同,那就太好了。

Just a misapplied abstraction it seems to me. A db cursor is an abstraction, meant for data set traversal.

From Wikipedia article on subject:

In computer science and technology, a database cursor is a control
structure that enables traversal over the records in a database.
Cursors facilitate subsequent processing in conjunction with the
traversal, such as retrieval, addition and removal of database
records. The database cursor characteristic of traversal makes cursors
akin to the programming language concept of iterator.

And:

Cursors can not only be used to fetch data from the DBMS into an
application but also to identify a row in a table to be updated or
deleted. The SQL:2003 standard defines positioned update and
positioned delete SQL statements for that purpose. Such statements do
not use a regular WHERE clause with predicates. Instead, a cursor
identifies the row. The cursor must be opened and already positioned
on a row by means of FETCH statement.

If you check the docs on Python sqlite module, you can see that a python module cursor is needed even for a CREATE TABLE statement, so it's used for cases where a mere connection object should suffice - as correctly pointed out by the OP. Such abstraction is different from what people understand a db cursor to be and hence, the confusion/frustration on the part of users. Regardless of efficiency, it's just a conceptual overhead. Would be nice if it was pointed out in the docs that the python module cursor is bit different than what a cursor is in SQL and databases.

℡寂寞咖啡 2024-11-21 22:05:33

根据官方 docs connection.execute () 是创建中间光标对象的非标准快捷方式

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

According to the official docs connection.execute() is a nonstandard shortcut that creates an intermediate cursor object:

Connection.execute
This is a nonstandard shortcut that creates a cursor object by calling the cursor() method, calls the cursor’s execute() method with the parameters given, and returns the cursor.

倾城泪 2024-11-21 22:05:33

12.6.8。使用 sqlite3 高效ly

12.6.8.1。使用快捷方式方法

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

sqlite3 文档;重点是我的。)

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

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

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

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

但是,如果您确定不会进行切换,那么我认为采用 connection.execute 快捷方式并“高效”是完全可以的。

12.6.8. Using sqlite3 efficiently

12.6.8.1. Using shortcut methods

Using the nonstandard execute(), executemany() and executescript() methods of the Connection object, your code can be written more concisely because you don’t have to create the (often superfluous) Cursor objects explicitly. Instead, the Cursor objects are created implicitly and these shortcut methods return the cursor objects. This way, you can execute a SELECT statement and iterate over it directly using only a single call on the Connection object.

(sqlite3 documentation; emphasis mine.)

Why not just use the connection object?

Because those methods of the connection object are nonstandard, i.e. they are not part of Python Database API Specification v2.0 (PEP 249).

As long as you use the standard methods of the Cursor object, you can be sure that if you switch to another database implementation that follows the above specification, your code will be fully portable. Perhaps you will only need to change the import line.

But if you use the connection.execute there is a chance that switching won't be that straightforward. That's the main reason you might want to use cursor.execute instead.

However if you are certain that you're not going to switch, I'd say it's completely OK to take the connection.execute shortcut and be "efficient".

我的黑色迷你裙 2024-11-21 22:05:33

您需要一个游标对象来获取结果。您的示例之所以有效,是因为它是一个 INSERT,因此您不会尝试从中获取任何行,但是如果您查看 sqlite3 docs,您会注意到连接对象上没有任何 .fetchXXXX 方法,因此如果您尝试执行 SELECT 而不使用光标,您将无法获取结果数据。

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

You need a cursor object to fetch results. Your example works because it's an INSERT and thus you aren't trying to get any rows back from it, but if you look at the sqlite3 docs, you'll notice that there aren't any .fetchXXXX methods on connection objects, so if you tried to do a SELECT without a cursor, you'd have no way to get the resulting data.

Cursor objects allow you to keep track of which result set is which, since it's possible to run multiple queries before you're done fetching the results of the first.

血之狂魔 2024-11-21 22:05:33

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

It gives us the ability to have multiple separate working environments through the same connection to the database.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文