您能在這里看到啥
- 運行效果
- 數(shù)據(jù)庫準(zhǔn)備
- 數(shù)據(jù)庫創(chuàng)建
- 創(chuàng)建遇到的問題
- DEMO地址
運行效果

數(shù)據(jù)庫準(zhǔn)備
首先,我們先把需要使用的第三方庫準(zhǔn)備一下,這樣也會加快我們的開發(fā)節(jié)奏.??
第三方
# 本地數(shù)據(jù)庫
sqflite: ^2.0.2+1
# 提供了大量方法,以便你能正確的定義數(shù)據(jù)庫在磁盤上的存儲位置
path: ^1.8.0
# 自己寫的方便項目開發(fā)的插件
hzy_normal_widget: ^0.0.4
# 加載動畫
flutter_easyloading: ^3.0.5
數(shù)據(jù)庫創(chuàng)建
- 創(chuàng)建數(shù)據(jù)庫
/// 通過sqflite 提供的方法,可以直接獲取到,數(shù)據(jù)庫存儲的路徑
String databasePath = await getDatabasesPath();
/// 再通過path提供的方法,直接生成數(shù)據(jù)庫的原始路徑
String path = join(databasePath, SqlConfig.dbname);
try {
/// 數(shù)據(jù)庫創(chuàng)建完成
db = await openDatabase(path);
} catch (e) {
/// 走這里的話,說明數(shù)據(jù)創(chuàng)建失敗,你需要排查一下,是不是路徑問題
debugprint('CreateTables init Error $e');
}
-
創(chuàng)建表
對于創(chuàng)建表,這里就需要你,根據(jù)業(yè)務(wù)需求,去自己創(chuàng)建了,我這邊就簡單的舉個例子,說明一下怎么創(chuàng)建表.第一步:定義數(shù)據(jù)表字段類型
- 我一般會先創(chuàng)建業(yè)務(wù)模型,從我們??運行效果中,可以看到,UI表現(xiàn)層,有時間,發(fā)布內(nèi)容,
這樣的話,我們業(yè)務(wù)模型就可以設(shè)計如下所示
class ListModel { ListModel({ this.listid, /// 列表ID this.title, /// 發(fā)布內(nèi)容 this.createtime, /// 創(chuàng)建時間 this.updatetime, /// 更新時間 }) }當(dāng)然這只是最基礎(chǔ)的業(yè)務(wù)模型,不要誤會了.
-
根據(jù)數(shù)據(jù)模型創(chuàng)建數(shù)據(jù)表,當(dāng)然數(shù)據(jù)表肯定是包含模型的.
從上面的基礎(chǔ)模型中,我們來創(chuàng)建表.這四個參數(shù)肯定是要有的,然后就是這個文章的歸宿,肯定也是需要用戶ID,因為文章也得有歸宿啊.好,說干就干,那我們來一個最簡單的內(nèi)容數(shù)據(jù)表吧
static final String createListTable = ''' CREATE TABLE IF NOT EXISTS tableName ( listid INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT UNIQUE, uid BIGINT(20), title TEXT, createtime BIGINT(20), updatetime BIGINT(20) ) '''??,已經(jīng)是我們創(chuàng)建表的基礎(chǔ)語法,這里我簡單說一下,上面的大寫字段 代表的意識
// 創(chuàng)建表的語句,意思是如果表不存在就去創(chuàng)建 CREATE TABLE IF NOT EXISTS tablename // 主鍵 遞增 INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT UNIQUE // 代表字符串 TEXT // int 類型 最大多少位 BIGINT // 用這個修飾的字段不能為null, NOT NULL當(dāng)然還有很多,需要的時候,自己查查資料就行,不是很難.
也是為了方便,我一般都不會把這種字符串,進行定義,這樣修改起來也方便,當(dāng)然也會減少手寫的出錯率.class SqlConfig { /// 數(shù)據(jù)庫名字 static String dbname = "hzysql.db"; /// 數(shù)據(jù)庫表版本 static int dbversion = 1; /// 創(chuàng)建表通用語句 static String creattable = 'CREATE TABLE IF NOT EXISTS'; /// 主鍵 遞增 static String primarykeyauto = 'INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT UNIQUE'; /// 不為null static String sqlnonull = 'NOT NULL'; /// text static String sqltext = 'TEXT'; /// 列表數(shù)據(jù)表名字 static String list = 'list'; }這樣??創(chuàng)建數(shù)據(jù)表的方式就如??所示
class NormalCreateTables { static final String createListTable = ''' ${SqlConfig.creattable} ${SqlConfig.list} ( ${ListModelId.listid} ${SqlConfig.primarykeyauto}, ${ListModelId.uid} BIGINT(20), ${ListModelId.name} ${SqlConfig.sqltext}, ${ListModelId.title} ${SqlConfig.sqltext}, ${ListModelId.createtime} BIGINT(20), ${ListModelId.updatetime} BIGINT(20) ) '''; /// 獲取所有的表 Map<String, String> getAllTables() { Map<String, String> map = <String, String>{}; map['list'] = createListTable; return map; } }好了,有了定義好的表,那我們就看一下怎么在數(shù)據(jù)里進行創(chuàng)建吧
第二步:創(chuàng)建表
- 獲取需要生成表的sql語句
//所有的sql語句 Map<String, String> allTableSqls = NormalCreateTables().getAllTables();- 檢查數(shù)據(jù)庫中是否有所有有表,返回需要創(chuàng)建的表
// 檢查數(shù)據(jù)庫中是否有所有有表,返回需要創(chuàng)建的表 Future<List<String>> getNoCreateTables(Map<String, String> tableSqls) async { Iterable<String> tableNames = tableSqls.keys; //已經(jīng)存在的表 List<String> existingTables = []; //要創(chuàng)建的表 List<String> createTables = []; /// 獲取數(shù)據(jù)庫中已經(jīng)存在的表 List tableMaps = await db! .rawQuery('SELECT name FROM sqlite_master WHERE type = "table"'); debugprint('tableMaps:' + tableMaps.toString()); for (var item in tableMaps) { existingTables.add(item['name']); } for (var tableName in tableNames) { if (!existingTables.contains(tableName)) { createTables.add(tableName); } } return createTables; }- 創(chuàng)建需要創(chuàng)建的表
//檢查需要生成的表 List<String> noCreateTables = await getNoCreateTables(allTableSqls); debugprint('noCreateTables:' + noCreateTables.toString()); /// 如果有需要創(chuàng)建的表 if (noCreateTables.isNotEmpty) { // 關(guān)閉上面打開的db,否則無法執(zhí)行open db!.close(); /// 打開數(shù)據(jù)庫 db = await openDatabase(path, version: 1, onCreate: (Database db, int version) async { debugprint('db created version is $version'); }, onOpen: (Database db) async { /// 創(chuàng)建新表 for (var sql in noCreateTables) { await db.execute(allTableSqls[sql]!); } debugprint('db補完表已打開'); }); } else { debugprint("表都存在,db已打開"); } List tableMaps = await db!.rawQuery('SELECT name FROM sqlite_master WHERE type = "table"'); debugprint('所有表:' + tableMaps.toString()); db!.close(); debugprint("db已關(guān)閉");至此,我們前期需要創(chuàng)建的表,到此就創(chuàng)建完成.
- 我一般會先創(chuàng)建業(yè)務(wù)模型,從我們??運行效果中,可以看到,UI表現(xiàn)層,有時間,發(fā)布內(nèi)容,
創(chuàng)建遇到的問題
在第一次創(chuàng)建表的時候,由于沒太注意語法,導(dǎo)致了??的問題

根據(jù)??報錯的提示,準(zhǔn)確的找到了發(fā)生問題地方,如??

相信很多同學(xué)都已經(jīng)找到問題了,對就是
就是最后這個多余的 ,
其實從??報錯提示也說的很清楚.
至此,創(chuàng)建數(shù)據(jù)庫已經(jīng)完成,下一篇文章我會詳細(xì)的講解,
增,刪,改,查,當(dāng)然刪除數(shù)據(jù)庫我是不會講的,大家有興趣,可以自己??.
DEMO地址
flutter-數(shù)據(jù)庫老相識之增、刪、改、查