[Python]第十三章 資料庫支援
阿新 • • 發佈:2019-01-04
文章目錄
13.1Python資料庫API
所有資料庫的大多數基本功能都相同,因此從理論上說,對於使用其中一種資料庫的程式,很容易對其進行修改以使用另一種資料庫。問題是即便不同模組提供的功能大致相同,它們的介面(API)也是不同的。為解決Python資料庫模組存在的這種問題,人們一致同意開發一個標準資料庫API(DB API)
13.1.1全域性變數
所有與DB API2.0相容的資料庫模組都必須包含三個全域性變數,它們描述了模組的特徵。通過檢查這些變數,看看給定的模組是否是程式能夠接受的。如果不是,就顯示合適的錯誤訊息並退出或者引發異常。
Python DB API的模組屬性
變 量 名 | 描 述 |
---|---|
apilevel | 使用的Python DB API版本 |
threadsafety | 模組的執行緒安全程度如何 |
paramstyle | 在SQL查詢中使用哪種引數風格 |
- API級別(apilevel):是一個字串常量,指出了使用的API版本。DB API 2.0指出,這個變數的值為’1.0’或’2.0’。
- 執行緒安全程度(threadsafety):是一個0~3(含)的整數。
0表示執行緒不能共享模組,而3表示模組是絕對執行緒安全的。1表示執行緒可共享模組本身,但不能共享連線(參見13.1.3節),而2表示執行緒可共享模組和連線,但不能共享遊標。 - 引數風格(paramstyle):表示當你執行多個類似的資料庫查詢時,如何在SQL查詢中插入引數。
13.1.2異常
異 常 | 超 類 | 描 述 |
---|---|---|
tandardError | 所有異常的超類 | |
arning | StandardError | 發生非致命問題時引發 |
rror | StandardError | 所有錯誤條件的超類 |
nterfaceError | Error | 與介面(而不是資料庫)相關的錯誤 |
atabaseError | Error | 與資料庫相關的錯誤的超類 |
ataError | DatabaseError | 與資料相關的問題,如值不在合法的範圍內 |
perationalError | DatabaseError | 資料庫操作內部的錯誤 |
ntegrityError | DatabaseError | 關係完整性遭到破壞,如鍵未通過檢查 |
nternalError | DatabaseError | 資料庫內部的錯誤,如遊標無效 |
rogrammingError | DatabaseError | 使用者程式設計錯誤,如未找到資料庫表 |
otSupportedError | DatabaseError | 請求不支援的功能如回滾 |
13.1.3連線和遊標
import sqlite3
con=sqlite3.connect('D:\Data\database.db')#連線物件
cur=con.cursor()#遊標物件
要使用底層的資料庫系統,必須先連線到它,為此可使用名稱貼切的函式connect。這個函式接受多個引數具體是哪些取決於要使用的資料庫。
函式connect的常用引數
引數名 | 描述 | 是否可選 |
---|---|---|
dsn | 資料來源名稱,具體含義隨資料庫而異 | 否 |
user | 使用者名稱 | 是 |
password | 使用者密碼 | 是 |
host | 主機名 | 是 |
database | 資料庫名稱 | 是 |
函式connect返回一個連線物件
連線對像的方法
方法名 | 描述 |
---|---|
close() | 關閉連線物件。之後,連線物件及其遊標將不可用 |
commit() | 提交未提交的事務——如果支援的話;否則什麼都不做 |
rollback() | 回滾未提交的事務(可能不可用) |
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 |
13.1.4型別
對於插入到某些型別的列中的值,底層SQL資料庫可能要求它們滿足一定的條件。為了能夠與底層SQL資料庫正確地互操作,DB API定義了一些建構函式和常量(單例),用於提供特殊的型別和值。
每個模組都必須實現表13-7所示的建構函式和特殊值。有些模組可能沒有完全遵守這一點。
名稱 | 描述 |
---|---|
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.2SQLite和PySQLite
SQLite小型資料庫引擎。它不需要作為獨立的伺服器執行,且可直接使用本地檔案,而不需要集中式資料庫儲存機制。
13.2.1起步
要使用Python標準庫中的SOLite,可通過匯入模組sqlite3來匯入它。
import sqlite3 #匯入模組
conn = sqlite3.connect('somedatabase.db') #建立連線
curs = conn.cursor() #獲取遊標
conn.commit() #提交修改(如果修改了資料)
conn.close() #關閉連線
13.2.2資料庫應用程式演示
目標:將文件轉化成資料庫
寫一個數據轉化檔案
###importdata.py 將資料匯入資料庫
import sqlite3
conn=sqlite3.connect('st.db')#建立連線
curs=conn.cursor()#獲得遊標
#定義一個去除兩邊~的函式
def convert(value):
if value.startswith('~'):
return value.strip('~')
if not value:#如果value是空值,則返回0
value='0'
return float(value)
#執行遊標——新建表
curs.execute('''
create table stu11(
id text primary key,
name text,
county test,
age float)
''')
query='insert into stu11 values (?,?,?,?)' #qmark風格使用問號來標記欄位
for line in open('sql.txt'):# 逐行讀取
fields=line.split('^') #每一行的文字用^分隔成列表
vals=[convert(f) for f in fields[:4]] #將該列表的每個元素執行convert函式後返回新的列表,取前4個元素([:4]中4不含)
curs.execute(query,vals)#執行遊標 ——儲存資料
print(vals)
conn.commit()#提交連線,針對改變資料庫的刪除、插入等操作,查詢不需要提交
conn.close()#斷開連線
----------------------------------------------------------------
['07276', 'Jack', 'China', '25']
['07274', 'May', 'Japan', '21']
這樣新建的st.db儲存有stu11這張表,表中有上述兩行資料
寫一個查詢檔案
#query.py
import sqlite3,sys
conn=sqlite3.connect('st.db')#建立連線
curs=conn.cursor()#獲得遊標
query='select * from stu11 where '+sys.argv[1]#sys.argv[1]外部給與的第一個引數
print(query)
curs.execute(query)
names=[f[0] for f in curs.description]#curs.description查看錶結構 f[0]得到域的名字/列名
for row in curs.fetchall():#curs.fetchall()得到執行sql語句後返回的記錄
for pair in zip(names,row):#zip縫合序列
print('{}:{}'.format(*pair))
print()
分解:
import sqlite3,sys
conn=sqlite3.connect('st.db')#建立連線
curs=conn.cursor()#獲得遊標
curs.execute('select * from stu11')
curs.description#查看錶結構
---------------------------------------------------------------
(('id', None, None, None, None, None, None),
('name', None, None, None, None, None, None),
('county', None, None, None, None, None, None),
('age', None, None, None, None, None, None))
-------------------------------------------------------------------
curs.fetchall()#得到執行語句後返回的記錄
[('07276', 'Jack', 'China', 25.0), ('07274', 'May', 'Japan', 21.0)]
#zip縫合函式
a=(('id', None, None, None, None, None, None),
('name', None, None, None, None, None, None),
('county', None, None, None, None, None, None),
('age', None, None, None, None, None, None))
aa=[f[0] for f in a]
b=[('07276', 'Jack', 'China', 25.0), ('07274', 'May', 'Japan', 21.0)]
for bb in b:
print(list(zip(aa,bb)))
---------------------------------------------------
[('id', '07276'), ('name', 'Jack'), ('county', 'China'), ('age', 25.0)]
[('id', '07274'), ('name', 'May'), ('county', 'Japan'), ('age', 21.0)]
延伸:使用pymysql連線MySQL資料庫
安裝命令:pip install PyMySQL
import pymysql
con=pymysql.connect('localhost','root','123456','execise')#(主機名,使用者名稱,密碼,資料庫名)與本地MYSQL資料庫一致
cur=con.cursor()
q='select * from student;'
cur.execute(q)
cur.fetchall()
#con.close()