簡介:
SQLite 內建函數比較有限,有時通過添加自訂函數(User-Defined Fuctions)的方式可以實現一些通過普通 SQL 操作無法實現或者實現很麻煩的功能;也可以替換 SQLite 原有的內建函數,使其符合我們的要求。本文側重說明在 Android 環境下的做法。
現在假設我們現在要在 Android 系統的視頻播放器增加一個按照副檔名排序的功能,如果不是用自訂函數,就需要先從多媒體資料庫中查詢出來視頻的路徑,然後取出視頻檔案的副檔名並進行排序,因為查詢得到的 Cursor 對象不可寫,所以需要產生一個 MatrixCursor,把排序後的資料寫入,最後返回這個 MatrixCursor。虛擬碼表示如下:
Cursor rawCursor = queryVideoFileNameFromDb(); HashMap<,String> idAndExtensionMap = getVideoFileExtension(rawCursor); Cursor result = sortAndCreateNewMatrixCursor(idAndExtensionMap); }
而如果我們能夠向 SQLite 註冊一個自訂函數,很多類似問題就要簡單不少。
1. 通過 C 語言介面添加自訂函數
如果使用的是 Android 提供的 sqlite 程式,需要修改 Android 源碼目錄下的 external/sqlite/android/sqlite3_android.cpp 檔案。註冊一個自訂函數,函數名稱是 get_file_ext,在 SQL 陳述式中的函數名稱是 "_GET_FILE_EXT",簡要代碼如下:
register_android_functions(sqlite3 * handle, err = sqlite3_create_function(handle, , (err != get_file_ext(sqlite3_context * context, argc, sqlite3_value ** }
然後編譯 external/sqlite,把編譯出來的 libsqlite.so 替換手機 /system/lib/ 下面的庫。使用該自訂函數也很簡單:
Cursor result = query("SELECT * FROM video SORT BY _GET_FILE_EXT(_data)" }
Note:如果不是在 Android 環境下,或者無法修改 Android 相關代碼,則需要自行通過 c 語言的介面操作資料庫,然後同樣使用 sqlite3_create_function 這個函數註冊自訂函數。如果使用的是 C#/Python/PHP 等語言,這些語言都有相應的 SQLite wrapper,可以類似的操作資料庫並註冊自訂函數。
2. 通過 Java 語言介面添加自訂函數
Android SQLiteDatabase 類裡面有一個添加自訂函數的隱藏介面(@hide),在 Android 源碼中編譯的話可以使用該介面,使用方法大致如下:
DatabaseHelper DatabaseHelper(Context context, String name, SQLiteDatabase.CursorFactory factory, db.addCustomFunction("_GET_FILE_EXT", 1 SQLiteDatabase.CustomFunction mGetFileExtension = String file = args[0 index = file.lastIndexOf("." (index != -1 && file.length() > index + 1 }
然後對這個資料庫進行查詢操作時,就可以使用我們添加的 _GET_FILE_EXT 函數了。Android 源碼目錄下的 pacakges/providers/MediaProvider 這個程式就使用了此介面,可以參考。
Note:對外發布的程式最好不要依賴隱藏的 Java 介面,相容性難以保證。
擴充閱讀:
- Create Or Redefine SQL Functions:建立自訂函數的解釋。
- Quickstart:使用 c 語言介面開啟 SQLite 資料庫的簡單範例程式碼。
轉載請註明出處:http://www.cnblogs.com/imouto/archive/2013/06/14/how-to-add-user-defined-functions-for-sqlite.html
本文外部鏡像:http://oteku.blogspot.com/2013/06/how-to-add-user-defined-functions-for-sqlite.html