在sqlite中,要將python的object存入sqlite,可以透過在class實作conform method,或者是透過sqlite提供的register_adapter,再者就是先將object轉換成sqlite有的type,在存入即可。不過透過以上的方式,其實實作邏輯都是相同,只有透過不同存取介面。
以conform為例:
import sqlite3 class Point(object): def __init__(self, x, y): self.x, self.y = x, y def __conform__(self, protocol): if protocol is sqlite3.PrepareProtocol: return "%f;%f" % (self.x, self.y) con = sqlite3.connect(":memory:") cur = con.cursor() p = Point(4.0, -3.2) cur.execute("select ?", (p,)) print cur.fetchone()[0]
point會將值轉成string,最後會輸出"4.000000;-3.200000",另外%f指的是浮點數。
透過register_adapter:
def adapt_point(point): return "%f;%f" % (point.x, point.y) sqlite3.register_adapter(Point, adapt_point)
只要在connect之前註冊好adapter,point就會自動轉成定義後格式。
如果要將以存入的值,轉回原先的object,這時可透過converter:
def convert_point(s): x, y = map(float, s.split(";")) return Point(x, y) # Register the converter sqlite3.register_converter("point", convert_point)
以上方式定義後,還必須在connect的時候,設定detect_types的參數,下面有3種方式。
第一種使用sqlite3.PARSE_DECLTYPES:
con = sqlite3.connect(":memory:", detect_types=sqlite3.PARSE_DECLTYPES) cur = con.cursor() cur.execute("create table test(p point)") cur.execute("insert into test(p) values (?)", (p,)) cur.execute("select p from test") print "with declared types:", cur.fetchone()[0]
必須要在create table的時候,就是先定義好point type,之後query出來會自訂轉成object。
第二種方式使用sqlite3.PARSE_COLNAMES:
con = sqlite3.connect(":memory:", detect_types=sqlite3.PARSE_COLNAMES) cur = con.cursor() cur.execute("create table test(p)") cur.execute("insert into test(p) values (?)", (p,)) cur.execute('select p as "p [point]" from test') print "with column names:", cur.fetchone()[0]
這種方式則是在query的時候,指定query欄位的type( p [point] )。
最後一種方式,就是兩種一起用:
con = sqlite3.connect(":memory:", detect_types=sqlite3.PARSE_DECLTYPES|sqlite3.PARSE_COLNAMES)