Programming sqlite with Tcl
2005/10/26 by coopermaa
Summary
什麼樣的資料庫稱得上是「小巧(small)、可內嵌(embeddable)而且支援 SQL 查詢語言的資料庫」?
答案是:sqlite,一套 Open Source 的關聯式資料庫。
sqlite 是一個「麻雀雖小卻五臟俱全」的資料庫,因為 sqlite 是一個體積僅僅 250KB 左右的 C Library,很適合內嵌的應用。sqlite 支援 SQL92 Standard,而且程式介面非常簡單,標準的程式介面除了 C 語言外,還有 Tcl 語言(其他語言也有支援,請上網查詢)。
「簡單易學,而且可嵌入應用程式裏」,這不也正是 Tcl 的特性嗎?所以,我覺得 Tcl 和 sqlite 實在是天生一對。
這份文件,是為了想以 Tcl + sqlite 寫資料庫 AP 的 Tclers 而整理的。我希望,這篇可以幫助你迅速上手學會 sqlite,讓你的程式,搖身一變,成為資料庫應用程式。我假設你熟悉 Tcl,修過資料庫系統課程,知道資料表正規化的原理和 SQL Statements(Select, Insert Into, Update, Delete, Create Table, Drop Table 等 Statements)。
Tcl + sqlite 五分鐘上手
六分鐘護一生,要讓 Tcl 和 sqlite 牽起手,從此快樂生活,只要五分鐘!不信的話,您現在可自個兒計算一下。
Opening and Closing database
要使用 sqlite 資料庫,你唯一的任務就是要記住 sqlite 這一個指令。看個例子:
package require sqlite ;# load sqlite package
sqlite db scores.db
這個範例會開啟 scores.db 這個資料庫檔,日後程式要存取 scores.db 的內容,全靠 db 這個新產生出來的指令,利用它來執行 SQL Statement 的工作(Select, Insert Into, Update, Delete, Create Table, Drop Table 等 SQL Statements),我們下一段就會看到一些範例。
要閉關資料庫,也是透過 db 指令:
db close ;# this will close scores.db
Executing SQL Statement
所有你想執行的 SQL Statement,全部丟給 eval method 就對了!
例如,我們要在 scores.db 資料庫建一張 scores table,只要將 CREATE TABLE 指令,丟給 db eval 去執行:
db eval {
CREATE TABLE scores (
id TEXT PRIMARY KEY,
name TEXT,
chinese NUMERIC,
english NUMERIC,
math NUMERIC
)
}
利用 Insert Into 指令,丟個幾筆資料到 scores table:
db eval {
INSERT INTO scores (id, name, chinese, english , math)
VALUES ('A0001', 'coopermaa', 90, 100, 100);
}
db eval {
INSERT INTO scores (id, name, chinese, english , math)
VALUES ('A0002', 'mei', 95, 90, 92)
}
db eval {
INSERT INTO scores (id, name, chinese, english , math)
VALUES ('A0003', 'XO', 99, 99, 99)
}
不小心把分數計錯了,得用 UPDATE 指令,把人家的分數更新回正確的才行:
db eval {
UPDATE scores SET chinese = 100 WHERE name = 'coopermaa'
}
我們在寫 Tcl Application 時,工作就是要組出正確的 SQL Statement,好丟給 db eval 去執行。這時怎麼組出正確的字串、引號有沒有配對正確,就是一件需要細心處理的事情:
puts -nonewline "Enter id: " ; gets stdin id
puts -nonewline "Enter name: " ; gets stdin name
puts -nonewline "Enter chinese socre: " ; gets stdin chinese
puts -nonewline "Enter english socre: " ; gets stdin english
puts -nonewline "Enter math socre: " ; gets stdin math
set query "INSERT INTO scores
VALUES ('$id', '$name', '$chinese', '$english', '$math') "
db eval $query
有時候,你得祭出 Transaction 這個法寶,讓自己的程式看起來高竿一點,唔,我是說「讓一系列的資料庫操作(a sequence of database operations),保證它們全部執行,否則,只要其中一步有錯,就回復到原始狀態(Rollback)」 :
db eval { BEGIN TRANSACTION }
db eval {
INSERT INTO scores
VALUES ("A0005", "char", 93, 94, 95);
INSERT INTO scores
VALUES ("A0006", "shishado", 95, 96, 97)
}
db eval { COMMIT TRANSACTION }
eval method 可以一次執行多個 SQL Statements,只要每個 SQL Statement 之間以分號隔開,如範例所示。
Fetching Records From Database
寫資料庫 AP,最常用到的指令,應該非 SELECT 指令莫屬了。
要處理 SELECT 指令傳回的資料,最簡單的形式是:
db eval {SELECT * FROM scores WHERE id = 'A0001'}
它會將結果按欄位順序,組成一個 list 傳回:
A0001 coopermaa 100 100 100
第二種形式是這樣:
db eval {
SELECT * FROM scores ORDER BY id
} data {
parray data
}
上列 Script 執行後,SELECT 指令所篩選出的每一筆記錄,都會放進 data 陣列裏,然後每筆記錄都會執行一次 parray data 這行指令印出陣列的內容。 請看這段 Script 的輸出:
data(*) = id name chinese english math
data(chinese) = 100
data(english) = 100
data(id) = A0001
data(math) = 100
data(name) = coopermaa
data(*) = id name chinese english math
data(chinese) = 95
data(english) = 90
data(id) = A0002
data(math) = 92
data(name) = mei
針對傳回的每一筆記錄,data(*) 會存放所有的欄位名稱(如上例的 id name chinese english math),而每一欄的資料,則是以欄位名稱當索引,放在陣列元素裏。因此,程式可以這樣嘛也通:
db eval {
SELECT * FROM scores ORDER BY id
} data {
puts "id = $data(id), name = $data(name)"
}
上列 Script 的輸出為:
id = A0001, name = coopermaa
id = A0002, name = mei
如果你不習慣使用陣列,還有第三式:
db eval {
SELECT * FROM scores ORDER BY id
} {
puts "id = $id, name = $name"
}
這會為你動態產生和欄位名稱相同的變數出來,所以 $id 的作用,就是取出 id 這一欄的資料了。
SQLite Database Browser
大部份資料庫系統都附有管理工具,譬如,Access、Enterprise Manager for SQL Server, phpMyAdmin for MySQL,方便使用者操作、維護資料庫。為了方便,我建議你準備一套圖形介面的工具,這裏我推薦 SQLite Database Browser,它是一個跨平台的、圖形介面(GUI based on Qt)的 sqlite 資料庫管理工具,你可以拿它來做這些事:



比較可惜的是,SQLite Database Browser 缺少像 Microsoft Access "資料庫關聯圖" 這種只要滑鼠就能輕鬆設好資料表關聯的工具。其實,偶爾從另一個角度看事情,會有令人意想不到的收獲的。雖然沒有方便的工具,輔助我們設計資料表的關聯, 我們倒不妨當它是練習 SQL Statement 的好機會, 練習利用 SQL Create Statement 來設定資料表的關聯,測驗測驗自己,看看當年有沒學好資料庫系統這門課。。
References
(阅读次数:)