1 概述
關系型數據庫(Relational Database, 以下簡稱RDB)是一種基于關系模型來管理數據的數據庫,是在SQLite基礎上提供一套完整的對本地數據庫進行管理的機制,為開發者提供無需編寫原生SQL語句即可實現數據增、刪、改、查等接口,同時開發者也可以直接運行原生SQL語句來滿足復雜的場景需要。關系型數據庫在應用卸載之后,才會被自動清除。
2 運作機制
RDB對外提供通用的接口,底層使用SQLite作為持久化存儲引擎,支持SQLite具有的所有數據庫特性。SQLite是一個進程內的庫,具有自給自足、無服務、零配置、事務性特性的SQL數據庫引擎。RDB包括但不限于事務、索引、視圖、觸發器、外鍵、參數化查詢和預編譯SQL語句。
3 使用場景
- 通訊錄
- 記事本
- 計算器歷史記錄
- App用戶登錄信息
- App主題
- ...
4 流程
5 詳細步驟
RDB對開發者提供的接口大部分為異步接口,均有callback
和Promise
兩種返回形式,接下來將會一一介紹。
5.1 導入模塊
import relationalStore from '@ohos.data.relationalStore';
5.2 配置數據庫相關信息
創建數據庫時需要配置數據庫相關信息,RDB提供管理關系型數據庫配置的StoreConfig
接口,其參數如表5-1所示:
表5-1 關系型數據庫配置參數
名稱 | 類型 | 必填 | 說明 |
---|---|---|---|
name | string | 是 | 數據庫文件名 |
securityLevel | SecurityLevel(詳見表5-2) | 是 | 設置數據庫安全級別 |
encrypt | boolean | 否 | 指定數據庫是否加密。true:加密。false:非加密。 |
表5-2 數據庫的安全級別枚舉
名稱 | 值 | 說明 |
---|---|---|
S1 | 1 | 數據庫安全級別為低級別,當數據泄露時會產生較低影響。如包含壁紙等系統數據的數據庫。 |
S2 | 2 | 數據庫安全級別為中級別,當數據泄露時會產生較大影響。如包含錄音、視頻等用戶生成數據或通話記錄等信息的數據庫。 |
S3 | 3 | 數據庫安全級別為高級別,當數據泄露時會產生重大影響。如包含用戶運動、健康、位置等信息的數據庫。 |
S4 | 4 | 數據庫安全級別為關鍵級別,當數據泄露時會產生嚴重影響。如包含認證憑據、財務數據等信息的數據庫。 |
const store_config = {
name: "RdbSample.db",
securityLevel: relationalStore.SecurityLevel.S4,
encrypt: true
}
5.3 創建數據庫
和MySQL、Oracle等數據庫類似,在使用之前需要先創建數據庫,RDB提供了getRdbStore()
方法用于創建數據庫,該方法需要傳入應用上下文Context
和數據庫配置信息StoreConfig
兩個參數,該方法有callback
和Promise
兩種返回形式,如表5-3所示。
表5-3 數據庫創建方法
方法名 | 描述 |
---|---|
getRdbStore(context: Context, config: StoreConfig, callback: AsyncCallback): void | 獲得一個相關的RdbStore,操作關系型數據庫。context: 應用上下文config: 數據庫配置信息callback: 回調函數,返回RdbStore對象 |
getRdbStore(context: Context, config: StoreConfig): Promise | 獲得一個相關的RdbStore,操作關系型數據庫。context: 應用上下文config: 數據庫配置信息Promise: Promise對象,返回RdbStore對象 |
// callback形式
relationalStore.getRdbStore(this.context, STORE_CONFIG, (err, rdbStore) => {
if (err) {
Log.error(TAG, "Get RdbStore fialed, err: " + JSON.stringify(err))
return;
}
// rdbStore相關操作
Log.info(TAG, "Get RdbStore successfully.");
})
// Promise形式
relationalStore.getRdbStore(this.context, STORE_CONFIG).then((rdbStore) => {
// rdbStore相關操作
Log.info(TAG, "Get RdbStore successfully.");
}).catch((err) => {
Log.error(TAG, "Get RdbStore fialed, err: " + JSON.stringify(err))
})
注:RDB不僅提供了數據庫創建的方法,同時還提供了刪除數據庫方法,可以調用deleteRdbStore()
方法進行數據庫刪除,使用方式和getRdbStore()
方法類似。
5.4 數據表操作
創建數據庫后,獲取到RdbStore
實例。RdbStore
提供管理RDB方法的接口,在使用其增、刪、改、查等接口之前,需要使用executeSql
接口初始化數據表結構和相關數據。
5.4.1 創建數據表
executeSql()
方法執行包含指定參數但不返回值得SQL語句,有callback
和Promise
兩種形式,如表5-4所示。
表5-4 創建數據表方法
方法名 | 描述 |
---|---|
executeSql(sql: string,bindArgs: Array, callback: AsyncCallback): void | 執行包含指定參數但不返回值得SQL語句。sql: 指定要執行得SQL語句bindArgs: SQL語句中參數的值callback: 回調函數 |
executeSql(sql: string,bindArgs: Array): Promise | 執行包含指定參數但不返回值得SQL語句。sql: 指定要執行得SQL語句bindArgs: SQL語句中參數的值Promise: 無返回結果的Promise對象 |
注:表中的ValueType
用于表示允許的數據字段類型,當前僅支持表示值類型為數字的number
,表示值類型為字符的string
,表示值類型為布爾值的boolean
。
const sql = "CREATE TABLE IF NOT EXISTS USER (ID INTEGER PRIMARY KEY AUTOINCREMENT, USERNAME TEXT NOT NULL, PASSWORD TEXT NOT NULL)"
// callback形式
rdbStore.executeSql(sql, null, (err) {
if (err) {
Log.error(TAG, "ExecuteSql failed, err: " + JSON.stringify(err));
return;
}
Log.info(TAG, "Create table done.");
})
// Promise形式
rdbStore.executeSql(sql, null).then(() => {
Log.info(TAG, "Create table done.");
}).catch((err) => {
Log.error(TAG, "ExecuteSql failed, err: " + JSON.stringify(err));
})
5.4.2 新增數據
RdbStore
提供了單條數據插入和批量數據插入兩種為數據表新增數據的方法,如表5-5所示。
表5-5 新增數據方法
方法名 | 描述 |
---|---|
insert(table: string, values: ValuesBucket, callback: AsyncCallback):void | 向表中插入一行數據。table: 插入數據的目標表名稱values: 插入到表中的數據行callback: 回調函數。插入成功,返回行ID,否則返回-1 |
insert(table: string, values: ValuesBucket): Promise | 向表中插入一行數據。table: 插入數據的目標表名稱values: 插入到表中的數據行Promise: Promise對象。插入成功,返回行ID,否則返回-1 |
batchInsert(table: string, values: Array, callback: AsyncCallback):void | 向表中插入一組數據table: 插入數據的目標表名稱插入到表中的一組數據callback: 回調函數。插入成功,返回插入的數據個數,否則返回-1 |
batchInsert(table: string, values: Array):Promise | 向表中插入一組數據table: 插入數據的目標表名稱插入到表中的一組數據Promise: Promise對象。插入成功,返回插入的數據個數,否則返回-1 |
注:表5-5中ValuesBucket
是用于存儲鍵值對的類型,其鍵為string
類型,值類型可為ValueType|Uint8Array|null
。
const tableName = "USER";
const valueBacket = {
"USERNAME": "Admin",
"PASSWORD": "123456"
}
// insert callback形式
rdbStore.insert(tableName, valueBucket, (err, rowId) => {
if (err) {
Log.error(TAG, "Insert data failed, err: " + JSON.stringify(err));
return;
}
Log.info(TAG, "Insert data successful, rowId = " + rowId);
})
// insert Promise形式
rdbStore.insert(tableName, valueBucket).then((rowId) => {
Log.info(TAG, "Insert data successful, rowId = " + rowId);
}).catch((err) => {
Log.error(TAG, "Insert data failed, err: " + JSON.stringify(err));
})
const valueBuckets = [{
"USERNAME": "aaa",
"PASSWORD": "123456"
}, {
"USERNAME": "bbb",
"PASSWORD": "123456"
}]
// batchInsert callback形式
rdbStore.batchInsert(tableName, valueBuckets, (err, count) => {
if (err) {
Log.error(TAG, "batchInsert data failed, err: " + JSON.stringify(err));
return;
}
Log.info(TAG, "batchInsert data successful, count = " + count);
})
// batchInsert Promise形式
rdbStore.batchInsert(tableName, valueBuckets).then((count) => {
Log.info(TAG, "batchInsert data successful, count = " + count);
}).catch((err) => {
Log.error(TAG, "batchInsert data failed, err: " + JSON.stringify(err));
})
5.4.3 更新數據
RdbStore
提供了根據RdbPredicates
指定實例對象和根據DataSharePredicates
指定實例對象兩種方式更新數據表中的數據,兩種方式均有callback
和Promise
形式,如表5-6所示。
RdbPredicates
和DataSharePredicates
均用于數據表中用來代表數據實體的性質、特征或者數據實體之間關系的詞項,主要用于定義數據表的操作條件。如設置根據賬號查找用戶信息的條件,或者根據賬號修改用戶密碼的條件。兩者區別在于使用前者需要先指定操作的數據表名稱,同時前者為分布式數據操作做了擴充。使用后者需要導入新模塊import dataSharePredicates from '@ohos.data.dataSharePredicates';
表5-6 更新數據方法
方法名 | 描述 |
---|---|
update(values: ValuesBucket, predicates: RdbPredicates, callback: AsyncCallback):void | 根據RdbPredicates的指定實例對象更新數據庫中的數據。values: 數據表中要更新的數據行predicates: RdbPredicates的實例對象指定的更新條件callback: 回調函數,返回受影響的行數 |
update(values: ValuesBucket, predicates: RdbPredicates):Promise | 根據RdbPredicates的指定實例對象更新數據庫中的數據。values: 數據表中要更新的數據行predicates: RdbPredicates的實例對象指定的更新條件Promise: Promise對象,返回受影響的行數 |
update(table: string, values: ValuesBucket, predicates: dataSharePredicates.DataSharePredicates, callback: AsyncCallback): void | 根據DataSharePredicates的指定實例對象更新數據表的數據。table: 更新數據表的名稱values: 數據表中要更新的數據行predicates: DataSharePredicates的實例對象指定的更新條件callback: 回調函數,返回受影響的行數 |
update(table: string, values: ValuesBucket, predicates: dataSharePredicates.DataSharePredicates): Promise | 根據DataSharePredicates的指定實例對象更新數據表的數據。table: 更新數據表的名稱values: 數據表中要更新的數據行predicates: DataSharePredicates的實例對象指定的更新條件Promise: Promise對象,返回受影響的行數 |
const tableName = "USER";
const valueBucket = {
"USERNAME": "aaa",
"PASSWORD": "123456789"
}
// RdbPredicates
let predicates = new relationalStore.RdbPredicates(tableName);
predicates.equalTo("USERNAME", "aaa");
// update callback形式
rdbStore.update(valueBucket, predicates, (err, rows) => {
if (err) {
Log.error(TAG, "Updated failed, err: " + JSON.stringify(err));
return;
}
Log.info(TAG, "Updated row count: " + rows);
})
// update Promise形式
rdbStore.update(valueBucket, predicates).then((rows) => {
Log.info(TAG, "Updated row count: " + rows);
}).catch((err) => {
Log.error(TAG, "Updated failed, err: " + JSON.stringify(err));
})
// DataSharePredicates
let predicates = new dataSharePredicates.DataSharePredicates();
predicates.equalTo("USERNAME", "aaa");
// update callback形式
rdbStore.update(tableName, valueBucket, predicates, (err, rows) => {
if (err) {
Log.error(TAG, "Updated failed, err: " + JSON.stringify(err));
return;
}
Log.info(TAG, "Updated row count: " + rows);
})
// update Promise形式
rdbStore.update(tableName, valueBucket, predicates).then((rows) => {
Log.info(TAG, "Updated row count: " + rows);
}).catch((err) => {
Log.error(TAG, "Updated failed, err: " + JSON.stringify(err));
})
5.4.4 查詢數據
數據表數據的查詢和更新相似,RdbStore
也提供了RdbPredicates
和DataSharePredicates
兩種方式,如表5-7所示。不同之處在于返回的結果不同,更新數據返回受影響的行數,查詢數據返回的數據結果集ResultSet
,關于結果集詳細講解將在下一節介紹。
表5-7 查詢數據方法
方法名 | 描述 |
---|---|
query(predicates: RdbPredicates, columns: Array, callback: AsyncCallback): void | 根據RdbPredicates的指定實例對象條件查詢數據表中的數據。predicates: RdbPredicates的實例對象指定的查詢條件columns: 查詢的列名稱,為空則表示查詢所有列callback: 回調函數,操作成功,返回ResultSet對象 |
query(predicates: RdbPredicates, columns: Array): Promise | 根據RdbPredicates的指定實例對象條件查詢數據表中的數據。predicates: RdbPredicates的實例對象指定的查詢條件columns: 查詢的列名稱,為空則表示查詢所有列Promise: Promise對象,操作成功,返回ResultSet對象 |
query(table: string, predicates: dataSharePredicates.DataSharePredicates, columns: Array, callback: AsyncCallback): void | 根據DataSharePredicates的指定實例對象條件查詢數據表中的數據。table: 查詢數據表名稱predicates: DataSharePredicates的實例對象指定的查詢條件columns: 查詢的列名稱,為空則表示查詢所有列callback: 回調函數,操作成功,返回ResultSet對象 |
query(table: string, predicates: dataSharePredicates.DataSharePredicates, columns: Array): Promise | 根據DataSharePredicates的指定實例對象條件查詢數據表中的數據。table: 查詢數據表名稱predicates: DataSharePredicates的實例對象指定的查詢條件columns: 查詢的列名稱,為空則表示查詢所有列Promise: Promise對象,操作成功,返回ResultSet對象 |
const tableName = "USER";
// RdbPredicates
let predicates = new relationalStore.RdbPredicates(tableName);
predicates.equalTo("USERNAME", "aaa");
// query callback形式
rdbStore.query(predicates, null, (err, resultSet) => {
if (err) {
Log.error(TAG, "Query failed, err: " + JSON.stringify(err));
return;
}
Log.info(TAG, "Query successful.");
Log.info(TAG, "ResultSet column count: " + resultSet.columnCount);
})
// query Promise形式
rdbStore.query(predicates, null).then((resultSet) => {
Log.info(TAG, "Query successful.");
Log.info(TAG, "ResultSet column count: " + resultSet.columnCoun
}).catch((err) => {
Log.error(TAG, "Query failed, err: " + JSON.stringify(err));
})
// DataSharePredicates
let predicates = new dataSharePredicates.DataSharePredicates();
predicates.equalTo("USERNAME", "aaa");
// query callback形式
rdbStore.query(tableName, predicates, null, (err, resultSet) => {
if (err) {
Log.error(TAG, "Query failed, err: " + JSON.stringify(err));
return;
}
Log.info(TAG, "Query successful.");
Log.info(TAG, "ResultSet column count: " + resultSet.columnCount);
})
// query Promise形式
rdbStore.query(tableName, predicates, null).then((resultSet) => {
Log.info(TAG, "Query successful.");
Log.info(TAG, "ResultSet column count: " + resultSet.columnCount);
}).catch((err) => {
Log.error(TAG, "Query failed, err: " + JSON.stringify(err));
})
5.4.5 刪除數據
表5-8 刪除數據方法
方法名 | 描述 |
---|---|
delete(predicates: RdbPredicates, callback: AsyncCallback):void | 根據RdbPredicates指定實例對象從數據表中刪除數據predicates: RdbPredicates實例對象指定的刪除條件callback: 回調函數,返回受影響的行數 |
delete(predicates: RdbPredicates):Promise | 根據RdbPredicates指定實例對象從數據表中刪除數據predicates: RdbPredicates實例對象指定的刪除條件Promise: Promise對象,返回受影響的行數 |
delete(table: string, predicates: dataSharePredicates.DataSharePredicates, callback: AsyncCallback):void | 根據DataSharePredicates指定實例對象從數據表中刪除數據table: 刪除數據的數據表名稱predicates: DataSharePredicates實例對象指定的刪除條件callback: 回調函數,返回受影響的行數 |
delete(table: string, predicates: dataSharePredicates.DataSharePredicates):Promise | 根據DataSharePredicates指定實例對象從數據表中刪除數據table: 刪除數據的數據表名稱predicates: DataSharePredicates實例對象指定的刪除條件Promise: 回調函數,返回受影響的行數 |
const tableName = "USER";
// RdbPredicates
let predicates = new relationalStore.RdbPredicates(tableName);
predicates.equalTo("USERNAME", "aaa");
// delete callback
rdbStore.delete(predicates, (err, rows) => {
if (err) {
Log.error(TAG, "Delete failed, err: " + JSON.string(err));
return;
}
Log.info(TAG, "Delete rows: " + rows);
})
// delete Promise
rdbStore.delete(predicates).then((rows) => {
Log.info(TAG, "Delete rows: " + rows);
}).catch((err) => {
Log.error(TAG, "Delete failed, err: " + JSON.string(err));
})
// DataSharePredicates
let predicates = new dataSharePredicates.DataSharePredicates();
predicates.equalTo("USERNAME", "aaa");
// delete callback
rdbStore.delete(tableName, predicates, (err, rows) => {
if (err) {
Log.error(TAG, "Delete failed, err: " + JSON.string(err));
return;
}
Log.info(TAG, "Delete rows: " + rows);
})
// delete Promise
rdbStore.delete(tableName, predicates).then((rows) => {
Log.info(TAG, "Delete rows: " + rows);
}).catch((err) => {
Log.error(TAG, "Delete failed, err: " + JSON.string(err));
})
6 原生SQL操作數據表
RdbStore
不僅提供了適用于增刪改查簡單易操作的接口方法,同時還支持原生SQL語句的操作。
querySql()
方法支持使用指定SQL語句查詢數據表中的數據
const sql = "select * from user";
rdbStore.querySql(sql).then((resultSet) => {
Log.info(TAG, "Query successful.");
Log.info(TAG, "ResultSet column count: " + resultSet.columnCount);
}).catch((err) => {
Log.error(TAG, "Query failed, err: " + JSON.stringify(err));
})
7 小節
當然RdbStore
還提供了其他的方法,諸如在開始執行SQL語句之前開啟事務的beginTransaction()
方法、提交已執行的SQL語句的commit()
方法、回滾已執行的SQL語句的rollBack()
方法以及用于其他能力的方法。本節僅對RDB數據庫的簡單使用做了講解,其中涉及到RdbPredicates
、DataSharePredicates
、ResultSet
相關的更多內容將在后續封裝RDB工具類中詳細介紹。
-
數據庫
+關注
關注
7文章
3846瀏覽量
64685 -
關系型數據庫
+關注
關注
0文章
8瀏覽量
2345 -
OpenHarmony
+關注
關注
25文章
3744瀏覽量
16577
發布評論請先 登錄
相關推薦
評論