python基礎教程(第三版)學習筆記(十三)
第十三章 資料庫支援
本章討論Python資料庫API(一種連線到SQL資料庫的標準化方式),並演示如何使用這個API 來執行一些基本的SQL。 本章使用的是簡單資料庫SQLite。介紹一些SQLite資料庫知識。不要指望在本章得到多少資料庫操作的具體知識。另外本章學習很大一部分基於PEP 249(https://www.python.org/dev/peps/pep-0249/) 因此還要多瞭解PEP 249 中關於PEP 249 標準下用Python操作資料庫知識。
13.1 Python 資料庫 API
本節概述有關該API的基礎知識。
13.1.1 全域性變數
所有與DB API2.0相容的資料庫模組都必須包含三個全域性變數,它們描述了模組的特徵。
apilevel 使用的Python DB API版本 ,是一個字串常量,指出了使用的API版本,'1.0'或'2.0'。
threadsafety 模組的執行緒安全程度如何,是一個0~3(含)的整數。0表示執行緒不能共享模組,而3表 示模組是絕對執行緒安全的。1表示執行緒可共享模組本身,但不能共享連線,而2 表示執行緒可共享模組和連線,但不能共享遊標(cursor ——記住這個單詞)。
paramstyle 在SQL查詢中使用哪種引數風格 。表示當你執行多個類似的資料庫查詢時,如何在SQL查詢中插入參 數。'format'表示標準字串格式設定方式(使用基本的格式編碼),如在要插入引數的地方插 入%s。'pyformat'表示擴充套件的格式編碼,即舊式字典插入使用的格式編碼,如%(foo)s。除這些 Python風格外,還有三種指定待插入欄位的方式:'qmark'表示使用問號,'numeric'表示使用:1 和:2這樣的形式表示欄位(其中的數字是引數的編號),而'named'表示使用:foobar這樣的形式表 示欄位(其中foobar為引數名)。
(不要懵了,其實以上的知識編寫簡單程式時, 不會用到它們。 )
13.1.2 異常
DB API定義了多種異常,讓你能夠細緻地處理錯誤。
StandardError 所有異常的超類
Warning 繼承StandardError 發生非致命問題時引發
Error繼承 StandardError 所有錯誤條件的超類
InterfaceError繼承 Error 與介面(而不是資料庫)相關的錯誤
DatabaseError 繼承Error 與資料庫相關的錯誤的超類
DataError繼承 DatabaseError 與資料相關的問題,如值不在合法的範圍內
OperationalError 繼承DatabaseError 資料庫操作內部的錯誤
IntegrityError 繼承DatabaseError 關係完整性遭到破壞,如鍵未通過檢查
InternalError 繼承DatabaseError 資料庫內部的錯誤,如遊標無效
ProgrammingError繼承 DatabaseError 使用者程式設計錯誤,如未找到資料庫表
NotSupportedError繼承 DatabaseError 請求不支援的功能,如回滾
異常知識在出現異常時查詢就可以了,不可死記。
13.1.3 連線和遊標
要使用底層的資料庫系統,必須先連線到它,為此可使用名稱貼切的函式connect。這個函 數接受多個引數,具體是哪些取決於要使用的資料庫。
函式connect的常用引數 :
參 數 名 | 描 述 | 是否可選 |
---|---|---|
dsn | 資料來源名稱,具體含義隨資料庫而異 | 否 |
user | 使用者名稱 | 是 |
password | 使用者密碼 | 是 |
host | 主機名 | 是 |
database | 資料庫名稱 | 是 |
函式connect的具體使用 形如:
conn = db.connect('host=locahost port=3306 user=foo password=bar databasee=baz charset=utf8')
其中db為模組,引數host為主機名、port為主機埠,這樣就獲得了與資料庫的聯接。函式connect返回一個連線物件conn,表示當前到資料庫的會話。連線物件支援以下的方法。
close() 關閉連線物件。之後,連線物件及其遊標將不可用
commit() 提交未提交的事務——如果支援的話;否則什麼都不做
rollback() 回滾未提交的事務(可能不可用)
cursor() 返回連線的遊標物件
這裡有兩個常用方法一個是close()關閉聯接;和cursor()獲取遊標。
對資料庫的增、刪、改、查都離不開遊標,獲取遊標又獲取了對資料庫的使用權,操作資料庫就是用遊標物件的方法進行,熟練運用遊標物件的方法應該是不可忽視的。遊標物件的方法如下:
callproc(name[, params]) 使用指定的引數呼叫指定的資料庫過程(可選)
close() 關閉遊標。關閉後遊標不可用
execute(oper[, params]) 執行一個SQL操作——可能指定引數
executemany(oper, pseq) 執行指定的SQL操作多次,每次都序列中的一組引數
fetchone() 以序列的方式取回查詢結果中的下一行;如果沒有更多的行,就返回None
fetchmany([size]) 取回查詢結果中的多行,其中引數size的值預設為arraysize
fetchall() 以序列的序列的方式取回餘下的所有行
nextset() 跳到下一個結果集,這個方法是可選的
setinputsizes(sizes) 用於為引數預定義記憶體區域
setoutputsize(size[, col]) 為取回大量資料而設定緩衝區長度
遊標物件還有三個屬性分別是:
description 由結果列描述組成的序列(只讀)
rowcount 結果包含的行數(只讀)
arraysize fetchmany返回的行數,預設為1
使用遊標形如:
cursor = conn.cursor()
data_list=cursor. fetchmany(9)
'''
等等對資料庫進行一系列操作
'''
conn.commit() # 提交事務,僅僅查詢不需要此語句
cursor.close() # 關閉遊標
conn.close() # 關閉連線
以上語句只是演示,使用的模組不同格式不盡相同,但大體四步法,即連線、獲取遊標、使用遊標物件的方法對資料庫操作(提交事務)、關閉遊標、關閉聯接。
13.1.4 型別
對於插入到某些型別的列中的值,底層SQL資料庫可能要求它們滿足一定的條件。為了能夠 與底層SQL資料庫正確地互操作,DB API定義了一些建構函式和常量(單例),用於提供特殊的 型別和值。
Date(year, month, day) 建立包含日期值的物件
Time(hour, minute, second) 建立包含時間值的物件
Timestamp(y, mon, d, h, min, s) 建立包含時間戳的物件
DateFromTicks(ticks) 根據從新紀元開始過去的秒數建立包含日期值的物件
TimeFromTicks(ticks) 根據從新紀元開始過去的秒數建立包含時間值的物件
imestampFromTicks(ticks) 根據從新紀元開始過去的秒數建立包含時間戳的物件
Binary(string) 建立包含二進位制字串值的物件 STRING 描述基於字串的列(如CHAR)
BINARY 描述二進位制列(如LONG或RAW)
NUMBER 描述數字列
DATETIME 描述日期/時間列
ROWID 描述行ID列
13.2 SQLite 和 PySQLite
為SQLite的小型資料庫引擎。它不需要作為獨立的伺服器執行,且可直接使用本地文 件,而不需要集中式資料庫儲存機制。
較舊的 Python 版本,必須安裝 PySQLite 才能使用 SQLite 資料庫,可 從 https://github.com/ghaering/pysqlite 下載。 較新的 Python 版本,幾乎可以肯定已經有 PySQLite 。使用模組sqlite3實現PySQLite。
(關於sqlitr3的操作參見sqliste3 — DB-API 2.0 interface for SQLite databases地址:https://pysqlite.readthedocs.io/en/latest/sqlite3.html,如不嫌簡陋可參見我粗簡譯文。地址:https://blog.csdn.net/micorjun/article/details/83896280)
13.2.1 起步
要使用Python標準庫中的SQLite,可通過匯入模組sqlite3來匯入它。然後,就可建立直接到 資料庫檔案的連線。為此,只需提供一個檔名(可以是檔案的相對路徑或絕對路徑);如果指 定的檔案不存在,將自動建立它。建立如無路徑則僅臨時儲存在記憶體中,關閉編輯器資料庫消失。
import sqlite3
conn = sqlite3.connect('somedatabase.db')
接下來可從連接獲得遊標。
curs = conn.cursor()
這個遊標可用來執行SQL查詢。執行完查詢後,如果修改了資料,務必提交所做的修改,這 樣才會將其儲存到檔案中。
conn.commit()
你可以(也應該)在每次修改資料庫後都進行提交,而不是僅在要關閉連線前才這樣做。要 關閉連線,只需呼叫方法close。
conn.close()
13.2.2 資料庫應用程式示例
1、建立並填充資料庫表
import sqlite3
studs=[('張三','23','男','三班'),('李四','24','男','四班'),('王六妮','21','女','二班')]
conn = sqlite3 .connect ('.\\foo.db' )
c = conn.cursor()
# 建立表
c.execute('''create table food
(name text, age int, sex text,
classid real)
''')
#輸入資料
stus = 'INSERT INTO food VALUES (?,?,?,?)'
for line in studs:
valu=list(line)
c.execute(stus,valu)
conn.commit()
c.close()
資料庫如下圖:
2、搜尋並處理結果
資料庫使用起來非常簡單:建立一條連線並從它獲取一個遊標;使用方法execute執行SQL 查詢並使用諸如fetchall等方法提取結果。
import sqlite3, sys
conn = sqlite3.connect('.\\foo.db')
curs = conn.cursor()
query = 'SELECT * FROM "stocks"'
print(query)
curs.execute(query)
names = [f[0] for f in curs.description]
for row in curs.fetchall():
for pair in zip(names, row):
print('{}: {}'.format(*pair), end='\t')
print("查詢結束!")
查詢結果:
C:\Users\xx\AppData\Local\Programs\Python\Python37\python.exe E:/pythonProjects/gui
SELECT * FROM "food"
name: 張三 age: 23 sex: 男 classid: 三班 name: 李四 age: 24 sex: 男 classid: 四班 name: 王六妮 age: 21 sex: 女 classid: 二班 查詢結束!
Process finished with exit code 0
(待續)