SQLite 是一款輕量級的、被設計用於嵌入式系統的關聯式資料庫管理系統。SQLite 是一個實現自我依賴、純用戶端、零配置且支援事務的資料庫引擎。它由D. Richard Hipp首次開發,目前已是世界上最廣泛部署的開來源資料庫引擎。
本文中,我們將介紹如下內容:
建立一個SQLite 資料庫
複製代碼 代碼如下:
SQLiteConnection conn = new SQLiteConnection("Data Source=mytest.s3db");
conn.Open();
SQLite 資料插入
複製代碼 代碼如下:
/// <summary>
/// Allows the programmer to easily insert into the DB
/// </summary>
/// <param name="tableName">The table into which we insert the data.</param>
/// <param name="data">A dictionary containing the column names and data for the insert.</param>
/// <returns>A boolean true or false to signify success or failure.</returns>
public bool Insert(string tableName, Dictionary<string, string> data)
{
Boolean returnCode = true;
StringBuilder columnBuilder = new StringBuilder();
StringBuilder valueBuilder = new StringBuilder();
foreach (KeyValuePair<string, string> val in data)
{
columnBuilder.AppendFormat(" {0},", val.Key);
valueBuilder.AppendFormat(" '{0}',", val.Value);
}
columnBuilder.Remove(columnBuilder.Length - 1, 1);
valueBuilder.Remove(valueBuilder.Length - 1, 1);
try
{
this.ExecuteNonQuery(string.Format("INSERT INTO {0}({1}) VALUES({2});",
tableName, columnBuilder, valueBuilder));
}
catch (Exception ex)
{
mLog.Warn(ex.ToString());
returnCode = false;
}
return returnCode;
}
複製代碼 代碼如下:
DateTime entryTime;
string name = string.Empty, title = string.Empty;
GetSampleData(out name, out title, out entryTime);
int id = random.Next();
insertParameterDic.Add("Id", id.ToString());
insertParameterDic.Add("Name", name);
insertParameterDic.Add("Title", title);
insertParameterDic.Add("EntryTime",
entryTime.ToString("yyyy-MM-dd HH:mm:ss"));
db.Insert("Person", insertParameterDic);
SQLite 的交易處理方式
Begin Transaction:
Commit Transaction:
Rollback Transaction:
複製代碼 代碼如下:
try
{
db.OpenTransaction();
Insert4Native();
db.CommiteTransaction();
}
catch (System.Exception ex)
{
mLog.Error(ex.ToString());
db.RollbackTransaction();
}
SQLite 的索引
索引是一種用來最佳化查詢的特性,在資料中分為聚簇索引和非聚簇索引;前者是由資料庫中資料群組織方式決定的,比如我們在往資料庫中一條一條插入資料時,聚簇索引能夠保證按順序插入,插入後資料的位置和結構不變。非聚簇索引是指我們手動、顯式建立的索引,可以為資料庫中的每個列建立索引,和字典中的索引類似,遵循的原則是對有分散性和組合型的列建立索引,以利於大資料和複雜查詢情況下提高查詢效率。
複製代碼 代碼如下:
/// <summary>
/// Create index
/// </summary>
/// <param name="tableName">table name</param>
/// <param name="columnName">column name</param>
/// <param name="indexName">index name</param>
public void CreateIndex(string tableName, string columnName, string indexName)
{
string createIndexText = string.Format("CREATE INDEX {0} ON {1} ({2});",
indexName, tableName, columnName);
ExecuteNonQuery(createIndexText);
}
簡單查詢、無關資料庫大小情況下對查詢效率的測試結果如下(700,000條資料):
複製代碼 代碼如下:
string sql = "SELECT LeafName FROM File WHERE Length > 5000";
複雜查詢情況下對查詢效率的測試結果如下(~40,000條資料):
複製代碼 代碼如下:
string sql = "SELECT folder.Location AS FilePath"
+ "FROM Folder folder LEFT JOIN File file ON file.ParentGuid=folder.Guid"
+"WHERE file.Length > 5000000 GROUP BY File.LeafName";
SQLite 的觸發器(Trigger)
觸發器是指當一個特定的資料庫事件(DELETE, INSERT, or UPDATE)發生以後自動執行的資料庫操作, 我們可以把觸發器理解為進階語言中的事件(Event)。
假設我有兩個表:
Folder(Guid VCHAR(255) NOT NULL, Deleted BOOLEAN DEFAULT 0)
File(ParentGuid VCHAR(255) NOT NULL, Deleted BOOLEAN DEFAULT 0)
在Folder 表中建立一個觸發器Update_Folder_Deleted:
複製代碼 代碼如下:
CREATE TRIGGER Update_Folder_Deleted UPDATE Deleted ON Folder
Begin
UPDATE File SET Deleted=new.Deleted WHERE ParentGuid=old.Guid;
END;
建立完觸發器以後在執行以下語句:
複製代碼 代碼如下:
UPDATE Folder SET Deleted=1 WHERE Guid='13051a74-a09c-4b71-ae6d-42d4b1a4a7ae'
以上語句將會導致下面的語句自動執行:
複製代碼 代碼如下:
UPDATE File SET Deleted=1 WHERE ParentGuid='13051a74-a09c-4b71-ae6d-42d4b1a4a7ae'
SQLite 的視圖(View)
視圖可以是一個虛擬表,裡面可以儲存按照一定條件過濾出來的資料集合,這樣我們再下次想得到這些特定資料集合的時候就不用通過複雜查詢來獲得,簡單的查詢指定視圖就可以得到想要的資料。
在下個例子中,我們建立一個簡單的視圖:
基於上面的查詢結果我們建立一個視圖:
SQLite 命令列工具
SQLite 庫中包含了一個SQLite3.exe 的命令列工具,它可以實現SQLite 各項基本操作。這裡只介紹一下如何使用它來分析我們的查詢結果:
1. CMD->sqlite3.exe MySQLiteDbWithoutIndex.s3db
2. 開啟EXPLAIN 功能並分析指定查詢結果
3. 重新使用命令列開啟一個有索引的資料庫並執行前兩步
4. 通過比較兩個不同查詢語句的分析結果,我們可以發現如果查詢過程中使用了索引,SQLite 會在detail 列中提示我們。
5. 要注意的是每條語句後面都要加分號“;”
SQLite一些常見的使用限制
1. SQLite 不支援Unicode 字元的大小寫比較,請看以下測試結果:
2. 如何處理SQLite 逸出字元:
複製代碼 代碼如下:
INSERT INTO xyz VALUES('5 O''clock');
3. 一條複合SELECT語句的條數限制:
一條複合查詢語句是指多條SELECT語句由 UNION, UNION ALL, EXCEPT, or INTERSECT 串連起來. SQLite進程的代碼產生器使用遞迴演算法來組合SELECT語句。為了降低堆棧的大小,SQLite 的設計者們限制了一條複合SELECT語句的條目數量。 SQLITE_MAX_COMPOUND_SELECT的預設值是500. 這個值沒有嚴格限制,在實踐中,幾乎很難看到一條複合查詢語句的條目數大於500的。
這裡提到複合查詢的原因是我們可以使用它來協助我們快速插入大量資料:
複製代碼 代碼如下:
public void Insert4SelectUnion()
{
bool newQuery = true;
StringBuilder query = new StringBuilder(4 * ROWS4ACTION);
for (int i = 0; i < ROWS4ACTION; i++)
{
if (newQuery)
{
query.Append("INSERT INTO Person");
newQuery = false;
}
else
{
query.Append(" UNION ALL");
}
DateTime entryTime;
string name = string.Empty, title = string.Empty;
GetSampleData(out name, out title, out entryTime);
int id = random.Next();
query.AppendFormat(" SELECT '{0}','{1}','{2}','{3}'", id, name, title, entryTime.ToString("yyyy-MM-dd HH:mm:ss"));
if (i % 499 == 0)
{
db.ExecuteNonQuery(query.ToString());
query.Remove(0, query.Length);
newQuery = true;
}
}
//executing remaining lines
if (!newQuery)
{
db.ExecuteNonQuery(query.ToString());
query.Remove(0, query.Length);
}
}