Tại sao bạn cần tạo một con trỏ khi truy vấn cơ sở dữ liệu sqlite?


133

Tôi hoàn toàn mới đối với mô-đun sqlite3 của Python (và SQL nói chung cho vấn đề đó) và điều này hoàn toàn làm tôi thất vọng. Việc thiếu các mô tả của cursorcác đối tượng (đúng hơn là sự cần thiết của chúng) cũng có vẻ kỳ quặc.

Đoạn mã này là cách làm việc ưa thích:

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

Điều này không phải, mặc dù nó hoạt động tốt và không có (dường như vô nghĩa) cursor:

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

Bất cứ ai có thể cho tôi biết tại sao tôi cần một cursor?
Nó chỉ giống như vô nghĩa trên đầu. Đối với mọi phương thức trong tập lệnh của tôi truy cập cơ sở dữ liệu, tôi phải tạo và hủy một cursor?
Tại sao không chỉ sử dụng connectionđối tượng?

Câu trả lời:


60

Nó chỉ là một sự trừu tượng sai lầm đối với tôi. Một con trỏ db là một sự trừu tượng hóa, có nghĩa là truyền tải dữ liệu.

Từ bài viết Wikipedia về chủ đề :

Trong khoa học và công nghệ máy tính, con trỏ cơ sở dữ liệu là một cấu trúc điều khiển cho phép truyền qua các bản ghi trong cơ sở dữ liệu. Các con trỏ tạo điều kiện cho việc xử lý tiếp theo kết hợp với truyền tải, chẳng hạn như truy xuất, thêm và xóa các bản ghi cơ sở dữ liệu. Đặc tính con trỏ cơ sở dữ liệu của traversal làm cho các con trỏ gần giống với khái niệm ngôn ngữ lập trình của iterator.

Và:

Các con trỏ không chỉ có thể được sử dụng để tìm nạp dữ liệu từ DBMS vào một ứng dụng mà còn để xác định một hàng trong bảng sẽ được cập nhật hoặc xóa. Tiêu chuẩn SQL: 2003 xác định cập nhật định vị và xóa các câu lệnh SQL cho mục đích đó. Các câu lệnh như vậy không sử dụng mệnh đề WHERE thông thường với các vị ngữ. Thay vào đó, một con trỏ xác định hàng. Con trỏ phải được mở và được định vị trên một hàng bằng câu lệnh FETCH.

Nếu bạn kiểm tra các tài liệu trên mô-đun sqlite Python , bạn có thể thấy rằng mô-đun python cursorlà cần thiết ngay cả đối với một CREATE TABLEcâu lệnh, vì vậy nó được sử dụng cho các trường hợp mà một connectionđối tượng đơn thuần phải đủ - như được OP chỉ ra chính xác. Sự trừu tượng hóa như vậy khác với những gì mọi người hiểu về con trỏ db và do đó, sự nhầm lẫn / thất vọng về phía người dùng. Bất kể hiệu quả, nó chỉ là một chi phí khái niệm. Sẽ rất tuyệt nếu được chỉ ra trong các tài liệu rằng mô-đun python cursorhơi khác so với con trỏ trong SQL và cơ sở dữ liệu.


7
+1 để thừa nhận sự khác biệt (lúc đầu) rất khó hiểu giữa các con trỏ db "truyền thống" và các con trỏ được sử dụng cho một db trong Python
Paul Draper

3
Trên thực tế, người ta có thể chỉ cần tạo một bảng đơn giản mà không cần sử dụng một con trỏ .
Serge Stroobandt

38

Bạn cần một đối tượng con trỏ để tìm nạp kết quả. Ví dụ của bạn hoạt động vì đó là INSERTvà do đó bạn không cố lấy lại bất kỳ hàng nào từ nó, nhưng nếu bạn xem sqlite3tài liệu , bạn sẽ nhận thấy rằng không có bất kỳ .fetchXXXXphương thức nào trên các đối tượng kết nối, vì vậy nếu bạn đã cố gắng thực hiện một SELECTmà không có một con trỏ, bạn sẽ không có cách nào để có được dữ liệu kết quả.

Các đối tượng con trỏ cho phép bạn theo dõi tập kết quả nào, vì có thể chạy nhiều truy vấn trước khi bạn tìm nạp kết quả của lần đầu tiên.


5
Cũng đáng lưu ý: PEP 249 không xác định executetrên một đối tượng kết nối, đây là một sqlite3phần mở rộng.
Cat Plus Plus

4
Nó vẫn hoạt động với các câu lệnh CHỌN: pastebin.com/5ZbhfEn7 . Lý do là bạn không gọi bất kỳ phương thức .fetchXXXX nào trên đối tượng kết nối, bạn đang gọi phương thức .fetchXXXX trên đối tượng được trả về bởi phương thức .execute () của kết nối.
Jack Bauer

1
Đúng. Nhưng một cách bạn kết thúc với một con trỏ (dường như) không cần thiết để truy vấn cơ sở dữ liệu: p
Jack Bauer

2
Rõ ràng sử dụng con trỏ là một thói quen tốt để tham gia, vì có thể sẽ có những dự án trong tương lai bạn làm việc ở nơi mọi thứ không tự động cam kết.
Amber

1
Đủ công bằng. Cảm ơn thông tin :)
Jack Bauer

36

Theo các tài liệu chính thức connection.execute()là một phím tắt không tiêu chuẩn tạo ra một đối tượng con trỏ trung gian:

Connection.execute
Đây là lối tắt không chuẩn để tạo đối tượng con trỏ bằng cách gọi phương thức con trỏ (), gọi phương thức exec () của con trỏ với các tham số đã cho và trả về con trỏ.


19

12.6.8. Sử dụng ly ly sqlite3 hiệu quả

12.6.8.1. Sử dụng các phương pháp phím tắt

Sử dụng không chuẩn execute() , executemany()executescript()phương pháp của đối tượng Connection, mã của bạn có thể được viết ngắn gọn hơn ly bởi vì bạn không cần phải tạo ra (thường không cần thiết ) Cursor các đối tượng một cách rõ ràng. Thay vào đó, các đối tượng Con trỏ được tạo hoàn toàn và các phương thức phím tắt này trả về các đối tượng con trỏ. Bằng cách này, bạn có thể thực thi một câu lệnh CHỌN và lặp lại nó trực tiếp bằng cách chỉ sử dụng một cuộc gọi duy nhất trên đối tượng Kết nối.

( tài liệu sqlite3 ; nhấn mạnh của tôi.)

Tại sao không chỉ sử dụng các đối tượng kết nối?

Bởi vì các phương thức của đối tượng kết nối là không chuẩn , tức là chúng không phải là một phần của Đặc tả API cơ sở dữ liệu Python v2.0 (PEP 249).

Miễn là bạn sử dụng các phương thức tiêu chuẩn của đối tượng Con trỏ, bạn có thể chắc chắn rằng nếu bạn chuyển sang triển khai cơ sở dữ liệu khác theo thông số kỹ thuật trên, mã của bạn sẽ hoàn toàn di động. Có lẽ bạn sẽ chỉ cần thay đổi importdòng.

Nhưng nếu bạn sử dụng, connection.executecó khả năng việc chuyển đổi sẽ không đơn giản như vậy. Đó là lý do chính bạn có thể muốn sử dụng cursor.executethay thế.

Tuy nhiên, nếu bạn chắc chắn rằng bạn sẽ không chuyển đổi, tôi sẽ nói hoàn toàn ổn khi sử dụng connection.executephím tắt và "hiệu quả".


1

Nó cho chúng ta khả năng có nhiều môi trường làm việc riêng biệt thông qua cùng một kết nối với cơ sở dữ liệu.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.