Mengapa Anda perlu membuat kursor saat menanyakan database sqlite?

133

Saya benar-benar baru untuk modul sqlite3 Python (dan SQL secara umum dalam hal ini), dan ini benar-benar membuat saya bingung. Kurangnya deskripsi cursorobjek yang melimpah (lebih karena kebutuhannya) juga tampak aneh.

Potongan kode ini adalah cara yang disukai untuk melakukan sesuatu:

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

Yang ini tidak, meskipun bekerja dengan baik dan tanpa (tampaknya tidak ada gunanya) cursor:

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

Adakah yang bisa memberi tahu saya mengapa saya perlu cursor?
Sepertinya overhead yang tidak ada gunanya. Untuk setiap metode dalam skrip saya yang mengakses database, saya seharusnya membuat dan menghancurkan cursor?
Mengapa tidak menggunakan connectionobjek saja?

Jack Bauer
sumber

Jawaban:

60

Bagi saya itu hanyalah abstraksi yang salah diterapkan. Kursor db adalah abstraksi, dimaksudkan untuk set data traversal.

Dari artikel Wikipedia tentang subjek :

Dalam ilmu dan teknologi komputer, kursor basis data adalah struktur kontrol yang memungkinkan traversal atas catatan dalam basis data. Kursor memfasilitasi pemrosesan selanjutnya bersama dengan traversal, seperti pengambilan, penambahan, dan penghapusan catatan basis data. Karakteristik kursor basis data dari traversal membuat kursor mirip dengan konsep bahasa pemrograman iterator.

Dan:

Kursor tidak hanya dapat digunakan untuk mengambil data dari DBMS ke dalam aplikasi tetapi juga untuk mengidentifikasi baris dalam tabel yang akan diperbarui atau dihapus. Standar SQL: 2003 mendefinisikan pembaruan posisi dan posisi menghapus pernyataan SQL untuk tujuan itu. Pernyataan seperti itu tidak menggunakan klausa WHERE reguler dengan predikat. Sebagai gantinya, sebuah kursor mengidentifikasi baris. Kursor harus dibuka dan sudah diposisikan pada baris melalui pernyataan FETCH.

Jika Anda memeriksa dokumen pada modul Python sqlite , Anda dapat melihat bahwa modul python cursordiperlukan bahkan untuk sebuah CREATE TABLEpernyataan, jadi itu digunakan untuk kasus-kasus di mana connectionobjek belaka sudah cukup - sebagaimana ditunjukkan dengan benar oleh OP. Abstraksi seperti itu berbeda dari apa yang orang pahami tentang kursor db dan karenanya, kebingungan / frustrasi di pihak pengguna. Terlepas dari efisiensi, itu hanya overhead konseptual. Akan lebih baik jika ditunjukkan dalam dokumen bahwa modul python cursorsedikit berbeda dari apa yang kursor dalam SQL dan database.

Basel Shishani
sumber
7
+1 untuk mengakui perbedaan (pada awalnya) yang sangat membingungkan antara kursor db "tradisional" dan kursor yang digunakan untuk db dengan Python
Paul Draper
3
Sebenarnya, seseorang dapat dengan mudah membuat tabel bahkan tanpa menggunakan kursor .
Serge Stroobandt
38

Anda memerlukan objek kursor untuk mengambil hasil. Contoh Anda berfungsi karena ini adalah INSERTdan dengan demikian Anda tidak mencoba mendapatkan baris apa pun darinya, tetapi jika Anda melihat sqlite3dokumen , Anda akan melihat bahwa tidak ada .fetchXXXXmetode pada objek koneksi, jadi jika Anda mencoba melakukannya a SELECTtanpa kursor, Anda tidak akan memiliki cara untuk mendapatkan data yang dihasilkan.

Objek kursor memungkinkan Anda untuk melacak set hasil yang mana, karena dimungkinkan untuk menjalankan beberapa kueri sebelum Anda selesai mengambil hasil yang pertama.

Amber
sumber
5
Juga patut diingat: PEP 249 tidak mendefinisikan executepada objek koneksi, ini adalah sqlite3ekstensi.
Cat Plus Plus
4
Ini masih berfungsi dengan pernyataan SELECT: pastebin.com/5ZbhfEn7 . Alasannya adalah bahwa Anda tidak memanggil metode .fetchXXXX pada objek koneksi, Anda memanggil metode .fetchXXXX pada objek yang dikembalikan oleh metode .execute () koneksi.
Jack Bauer
1
Iya. Tapi satu cara Anda berakhir dengan (tampaknya) kursor yang tidak perlu yang digunakan untuk query database: p
Jack Bauer
2
Menggunakan kursor secara eksplisit adalah kebiasaan yang baik untuk dilakukan, karena mungkin akan ada proyek di masa depan yang Anda kerjakan di mana segala sesuatu tidak dilakukan secara otomatis.
Amber
1
Cukup adil. Terima kasih atas informasinya :)
Jack Bauer
36

Menurut dokumen resmi connection.execute()adalah pintasan tidak standar yang membuat objek kursor menengah:

Connection.execute
Ini adalah pintasan tidak standar yang membuat objek kursor dengan memanggil metode kursor (), memanggil metode eksekusi kursor () dengan parameter yang diberikan, dan mengembalikan kursor.

pengguna
sumber
19

12.6.8. Menggunakan lylite3 efisien ly

12.6.8.1. Menggunakan metode pintas

Menggunakan metode tidak standar execute() , executemany()dan executescript()metode objek Sambungan, kode Anda dapat ditulis lebih ringkas karena Anda tidak harus membuat objek kursor (seringkali berlebihan ) secara eksplisit. Sebaliknya, objek kursor dibuat secara implisit dan metode pintas ini mengembalikan objek kursor. Dengan cara ini, Anda dapat menjalankan pernyataan SELECT dan beralih secara langsung menggunakan hanya satu panggilan pada objek Sambungan.

( dokumentasi sqlite3 ; penekanan milikku.)

Mengapa tidak menggunakan objek koneksi saja?

Karena metode-metode dari objek koneksi tidak standar , yaitu mereka bukan bagian dari Spesifikasi API Python Database v2.0 (PEP 249).

Selama Anda menggunakan metode standar objek Cursor, Anda dapat yakin bahwa jika Anda beralih ke implementasi database lain yang mengikuti spesifikasi di atas, kode Anda akan sepenuhnya portabel. Mungkin Anda hanya perlu mengubah importjalurnya.

Tetapi jika Anda menggunakan connection.executeada kemungkinan bahwa peralihan tidak akan semudah itu. Itulah alasan utama Anda mungkin ingin menggunakannya cursor.execute.

Namun jika Anda yakin bahwa Anda tidak akan beralih, saya akan mengatakan tidak apa-apa untuk mengambil jalan connection.executepintas dan menjadi "efisien".

AXO
sumber
1

Ini memberi kita kemampuan untuk memiliki beberapa lingkungan kerja yang terpisah melalui koneksi yang sama ke database.

Pelajar Python
sumber