web-dev-qa-db-ja.com

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

115
Jack Bauer

単なる誤用の抽象化のように思えます。 dbカーソルは、データセットトラバーサルを目的とした抽象化です。

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

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

そして:

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

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

52
Basel Shishani

結果を取得するにはカーソルオブジェクトが必要です。あなたの例はINSERTであり、それから行を戻そうとしていないので機能しますが、 sqlite3 docs 、あなたは.fetchXXXXメソッドは接続オブジェクトにあるため、カーソルなしでSELECTを実行しようとした場合、結果のデータを取得する方法はありません。

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

32
Amber

公式によれば docsconnection.execute()は、中間カーソルオブジェクトを作成する非標準のショートカットです。

Connection.execute
これは、cursor()メソッドを呼び出してカーソルオブジェクトを作成し、指定されたパラメーターでカーソルのexecute()メソッドを呼び出し、カーソルを返す非標準のショートカットです。

31
user

12.6.8。 sqlite3efficientlyの使用

12.6.8.1。 shortcutメソッドの使用

Connectionオブジェクトのnonstandardexecute()executemany()およびexecutescript()メソッドを使用して、コードを記述できますより簡潔になります。これは、(多くの場合superfluous)Cursorオブジェクトを明示的に作成する必要がないためです。代わりに、Cursorオブジェクトが暗黙的に作成され、これらのショートカットメソッドはカーソルオブジェクトを返します。このようにして、SELECTステートメントを実行し、Connectionオブジェクトで1回の呼び出しのみを使用して直接繰り返すことができます。

sqlite3のドキュメント ;私の強調。)

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

接続オブジェクトのメソッドは 非標準 であるため、つまり Python Database API Specification v2. (PEP 249)の一部ではありません。

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

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

ただし、切り替えないことが確実な場合は、connection.executeショートカットを使用して "効率的"であっても完全に問題ないと思います。

13
AXO

データベースへの同じ接続を介して、複数の個別の作業環境を使用することができます。

0
Python Learner