Flutter持久化存儲之sqflite詳細使用

前言

sqflite是一個輕量的關係型數據庫,以表的形式將較爲複雜的數據存儲到.db文件中(數據庫),同時支持安卓和IOS,簡單數據可直接使用 shared_preferences

1. 準備工作

1.1 添加依賴:

在pubspec.yaml文件下添加
path_provider是用來處理路徑相關的操作
dependencies:
  sqflite: ^1.3.0+2
  path_provider: ^1.6.9

1.2 安裝

如果保存了有自動執行則最好,如果沒有那麼在終端運行flutter packages get命令

1.3 導入

import 'package:sqflite/sqflite.dart';
import 'package:path_provider/path_provider.dart';

1.4 注意

 // SQLite支持的數據類型  不支持bool和DateTime
 // SQL類型 ==== Dart類型
 // integer ==== int
 // real    ==== num
 // text    ==== String
 // blob    ==== Uint8List

2. 使用流程

2.1 創建數據庫

// 數據庫文件路徑:可以根據自己的需求自己定 這裏使用的是外部存儲可見的目錄
// 可以將路徑打印出來 在手機上找到它
String databasePath=(await getExternalStorageDirectory()).path+"/demo.db";

// 打開數據庫  (若想數據庫只能讀取則使用openReadOnlyDatabase())
// 1 若數據庫不存在 則創建數據庫
// 2 若數據庫存在 version大於當前數據庫version 則升級
// 3 若數據庫存在 version小於當前數據庫version 則降級
// 4 若數據庫存在 version等於當前數據庫version 則不變
 Database database=await openDatabase(databasePath,version: 2,
  readOnly: false,      //   是否只讀
  singleInstance: true, //   是否單例
  // 第一個被調用的可選回調 配置數據庫使用SQL語句配置
  onConfigure: (Database database)async{
    await database.execute("PRAGMA foreign_keys = ON");
    print("配置數據庫");
  },
  // 創建數據庫回調
  onCreate: (Database database,int version)async{
    print("版本:$version 數據庫創建成功");
  },
  // 數據庫降級回調
  onDowngrade: (Database database,int oldVersion,int newVersion)async{
    print("版本$oldVersion 降級到 $newVersion");
  },
  // 數據庫升級回調
  onUpgrade: (Database database,int oldVersion,int newVersion)async{
    print("版本$oldVersion 升級到 $newVersion");
  },
  // 數據庫打開回調
  onOpen: (Database database){
    print("數據庫打開成功");
  },
);

2.2 創建數據表

// 使用execute方法執行SQL語句 注意:execute執行的SQL是沒有返回值的
database.execute('CREATE TABLE Test (id INTEGER PRIMARY KEY, name TEXT, value INTEGER, age REAL)');

2.3 增刪改查

2.3.1 where和whereArgs的使用
// 在查詢和更新刪除等語句中,會使用到where和whereArgs作爲條件及條件參數
// 此處以查詢爲例 更新和刪除請舉一反三
// 查詢test表中 name爲zs並且age爲18的記錄 
// where中 and代表並且(都滿足) or代表或者(滿足其一)
// where中的?爲佔位符 會依照順序被後面whereArgs中的數據替換
await database.query('test',where:"name=? and age=?",whereArgs: ["zs",18]).then((value) => print(value));
2.3.2 插入數據
// 插入數據  
//1.insert(表名,{"鍵":值},conflictAlgorithm(衝突算法:枚舉類型)) 返回行數
database.insert('test',{"name":'zs',"age":18}).then((value) => print(value));
// 2. 使用SQL語句進行插入 
// database.rawInsert("SQL語句");
2.3.3 刪除數據
// 刪除數據 
// 1.delete("表名",where(條件),whereArgs(條件參數))
// 此處爲尋找name爲zs的記錄
database.delete('test',where: "name=?",whereArgs: ["zs"]);  
// 2. 使用SQL語句進行刪除
// database.rawDelete("SQL語句");
2.3.4 更新數據
// 更新數據
// 1.update("表名",要修改的內容{'鍵':值},where(條件),whereArgs(條件參數),conflictAlgorithm(衝突算法:枚舉類型))
// 將name爲zs的記錄的name改爲ls,age改爲18
database.update('test', {"name":'ls',"age":18},where: "name=?",whereArgs: ['zs']);
// 2.使用SQL語句進行更新
// database.rawUpdate("SQL語句");
2.3.5 查詢數據
// 查詢數據
// 1.query(表名,{distinct,columns(返回哪些字段),where(條件),
// whereArgs(條件參數),groupBy(分組),having(分組後的進行條件查詢),
//  orderBy(排序),limit(一次讀幾條),offset(起始位置)}) 返回讀取到的結果(列表)
// 若沒有查詢條件 則返回這個表的數據
await database.query('test',                 //查詢的表名
  distinct: true,                              // 不重複
  where:"value=? and age=?",whereArgs: [1,18], // 查詢 value爲1並且age爲18的記錄
  columns: ["name","age"],                     // 返回的記錄只包含name和age兩個字段
  groupBy: "age",                              // 根據age分組
  orderBy: "age",                              // 根據age排序
  limit: 10,                                   // 一次讀取10條記錄
  offset: 5                                    // 從第5條記錄開始查詢
);
// 2. 使用SQL語句進行查詢
// database.rawQuery("SQL語句");

2.4 批處理 Batch

// 批處理SQL語句 往Batch中添加語句 但是這些語句並不會執行 需要調用commit方法 然後一次性執行
Batch batch=database.batch();
batch.insert("test",{"name":'ls'});
batch.insert("test",{"name":'ww'});
// noResult 是否不需要結果  continueOnError遇到異常是否繼續執行 
batch.commit(noResult: true,continueOnError: true).then((value) => print(value));

2.5 事務

// 事務
// 在事務中執行SQL語句 若發生異常 則進行回滾 即全部SQL語句無效
// 四大特徵:
// 1. 原子性:即事務中的語句爲一個整體 要麼全部執行 要麼全不執行
// 2. 一致性:保持數據的一致性 如轉賬 轉賬過後的總金額需要保持一致
// 3. 隔離性:多個事務併發時  互不干涉內部數據 處理的數據都是別的事務處理前或處理後的數據
// 4. 持久性:事務提交後 數據是持久不可更改的

database.transaction((txn)async{
  // txn基本有database中所有的操作 基本可以當做database使用
  txn.insert('test',{"name":'Rob'});
});

2.6 其他數據庫操作

// 數據庫是否打開
// print(database.isOpen);

//  獲取默認數據庫存放的路徑
getDatabasesPath().then((value) => print("默認數據庫路徑"+value));

// 根據路徑查看數據庫是否存在
databaseExists(databasePath).then((value) => print("數據庫是否存在:"+value.toString()));

// 設置數據庫版本
database.setVersion(666);

// 獲取數據庫版本
database.getVersion().then((value) => print(value));

// 關閉數據庫(數據庫文件還在)
// database.close(); 

//  刪除數據庫(數據庫文件不在)
// await deleteDatabase(databasePath);

根據官方文檔和源碼註解以及嘗試所得,若有所幫,點贊一下

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章