2011-06-11 540 views
75

我對Python's sqlite3 module(以及有關SQL的總體情況)完全陌生,而且這完全讓我失望。對於cursor objects(而不是他們的必要性)的描述的缺乏也很奇怪。爲什麼在查詢sqlite數據庫時需要創建一個遊標?

的這段代碼是做事的首選方式:

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對象?

回答

28

您需要一個遊標對象來獲取結果。你的例子的工作原理是INSERT,因此你不想從它那裏得到任何行,但是如果你看sqlite3 docs,你會注意到在連接對象上沒有任何.fetchXXXX方法,所以如果你嘗試過沒有遊標做SELECT,你將無法獲得結果數據。

遊標對象允許您跟蹤哪個結果集是哪個結果集,因爲在獲取第一個結果之前可以運行多個查詢。

+5

另外值得記住:[PEP 249](http://www.python.org/dev/peps/pep-0249/)沒有定義'連接對象上execute',這是一個'sqlite3'延期。 – 2011-06-11 19:50:30

+2

它仍然適用於SELECT語句:http://pastebin.com/5ZbhfEn7。原因是您沒有在連接對象上調用任何.fetchXXXX方法,所以您正在對由連接的.execute()方法返回的對象調用.fetchXXXX方法。 – 2011-06-12 03:10:18

+0

@傑克:是的,但是你仍然以某種方式結束了遊標。 – Amber 2011-06-12 07:15:23

20

根據官方docsconnection.execute()非標準快捷方式創建一箇中間遊標對象。

41

只是一個錯誤的抽象在我看來。數據庫遊標是一種抽象,用於數據集遍歷。

Wikipedia article on subject

在計算機科學與技術,數據庫光標控制 結構,使穿越了在數據庫中的記錄。 遊標有助於後續處理連同 遍歷,如檢索,添加和刪除數據庫 記錄。遍歷的數據庫遊標特性使得遊標 類似於迭代器的編程語言概念。

和:

光標不僅可以用於從DBMS數據放到一個 應用,而且在確定表中的行更新或刪除 。 SQL:2003標準定義了定位更新,並且爲此定位了刪除SQL語句。 這樣的語句不使用帶謂詞的常規WHERE子句。相反,光標 標識該行。遊標必須打開並且已經通過FETCH語句在一行上定位了 。

如果您檢查docs on Python sqlite module,你可以看到一個Python模塊cursor甚至爲CREATE TABLE語句所需,所以它的使用,其中僅connection對象應該足夠的情況下 - 如正確地指出由OP。這種抽象與人們對db光標的理解不同,因此也是用戶的困惑/沮喪。無論效率如何,這只是一個概念性開銷。如果在文檔中指出Python模塊cursor與SQL和數據庫中的遊標有點不同,那將會很好。

+3

用於確認(首先)「傳統」數據庫遊標與用於Python中數據庫的遊標之間的非常混淆的區別 – 2013-03-03 23:58:08

+0

實際上,人們可以明白地[即使不使用遊標也可以創建表](https:// xania.org/200711/python-sqlite-gotcha)。 – 2017-07-18 11:07:44

8

12.6.8。中使用sqlite3 高效 LY

12.6.8.1。使用快捷方法

使用Connection對象的非標準​​,executemany()executescript()方法,您可以編寫代碼更簡潔 LY,因爲你沒有創建(通常多餘)遊標明確的對象。相反,Cursor對象是隱式創建的,這些快捷方法返回遊標對象。這樣,您可以執行SELECT語句並直接使用Connection對象上的一次調用直接對其進行迭代。

sqlite3 documentation;重點煤礦。)

爲什麼不直接使用的連接對象?

由於連接對象的那些方法是nonstandard,即它們不是Python Database API Specification v2.0(PEP 249)的一部分。

只要你使用Cursor對象的標準方法,你可以肯定的是,如果你切換到遵循上述規範的另一個數據庫實現,你的代碼將完全便攜。也許你只需要改變import一行。

但是如果你使用的connection.execute有機會的切換不會是簡單的。這是你可能想用cursor.execute代替的主要原因。

但是,如果你確信你不會切換,我會說這是完全可以採取connection.execute快捷方式,是「有效的」。

相關問題