sqliteデータベースをクエリするときにカーソルを作成する必要があるのはなぜですか?


133

私は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オブジェクトを使用しないのですか?

回答:


60

抽象化を誤って適用しただけに思えます。dbカーソルは抽象化であり、データセットトラバーサル用です。

主題に関するウィキペディアの記事から:

コンピュータサイエンスおよびテクノロジーでは、データベースカーソルは、データベース内のレコードのトラバーサルを可能にする制御構造です。カーソルを使用すると、データベースレコードの取得、追加、削除など、トラバーサルに関連する後続の処理が容易になります。トラバーサルのデータベースカーソル特性により、カーソルはイテレータのプログラミング言語の概念に似ています。

そして:

カーソルは、DBMSからアプリケーションにデータをフェッチするためだけでなく、更新または削除するテーブルの行を識別するためにも使用できます。SQL:2003標準では、その目的のために位置付け更新および位置付け削除SQLステートメントを定義しています。そのようなステートメントは、述部を伴う通常のWHERE節を使用しません。代わりに、カーソルが行を識別します。カーソルは、FETCHステートメントによって開かれ、すでに行に配置されている必要があります。

Python sqlite moduleのドキュメントを確認するcursorと、CREATE TABLEステートメントでもpythonモジュールが必要であることがわかります。そのため、これは単なるconnectionオブジェクトで十分な場合に使用されます-OPによって正しく指摘されています。このような抽象化は、人々がdbカーソルを理解することとは異なり、したがって、ユーザーの混乱/フラストレーションとは異なります。効率に関係なく、それは単なる概念上のオーバーヘッドです。ドキュメントでpythonモジュールcursorがSQLやデータベース内のカーソルとは少し異なることが指摘されているといいでしょう。


7
+1は、「従来の」dbカーソルと、Pythonでdbに使用されるカーソルとの間の(最初は)非常に紛らわしい区別を認めたことです
Paul Draper


38

結果を取得するにはカーソルオブジェクトが必要です。あなたの例はそれがでありINSERT、したがってそこから行を取り戻そうとしないので機能しますが、sqlite3docsを見ると、.fetchXXXX接続オブジェクトにメソッドがないことに気付くでしょう。SELECTカーソルなしで、あなたは結果のデータを取得する方法がありませんと思います。

最初の結果のフェッチが完了する前に複数のクエリを実行することができるため、カーソルオブジェクトを使用すると、どの結果セットがどれであるかを追跡できます。


5
また、覚えておく価値があります。PEP249executeは接続オブジェクトを定義していませんsqlite3。これは拡張機能です。
Cat Plus Plus

4
SELECTステートメントでも引き続き機能します:pastebin.com/5ZbhfEn7。接続オブジェクトで.fetchXXXXメソッドを呼び出さないため、接続の.execute()メソッドによって返されたオブジェクトで.fetchXXXXメソッドを呼び出しています。
ジャックバウアー

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オブジェクトは暗黙的に作成され、これらのショートカットメソッドはカーソルオブジェクトを返します。このようにして、SELECTステートメントを実行し、Connectionオブジェクトに対して1回の呼び出しのみを使用して、そのステートメントを直接反復処理できます。

sqlite3のドキュメント ;強調は私のものです。)

なぜ接続オブジェクトを使用しないのですか?

接続オブジェクトのこれらのメソッドは非標準であるため、つまり、PythonデータベースAPI仕様v2.0(PEP 249)の一部ではありません。

Cursorオブジェクトの標準メソッドを使用している限り、上記の仕様に従う別のデータベース実装に切り替えると、コードは完全に移植可能になります。おそらく、import行を変更するだけで済みます。

しかし、使用する場合connection.execute、切り替えがそれほど簡単ではない可能性があります。これが、cursor.execute代わりに使用する主な理由です。

ただし、切り替えるつもりがないことが確実な場合は、connection.executeショートカットを使用して「効率的」にしても問題はありません。


1

これにより、データベースへの同じ接続を介して、複数の個別の作業環境を持つことができます。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.