0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

OpenHarmony关系型数据库概述

ITMING 来源:ITMING 作者:ITMING 2023-03-28 18:08 次阅读

1 概述

关系型数据库(Relational Database, 以下简称RDB)是一种基于关系模型来管理数据的数据库,是在SQLite基础上提供一套完整的对本地数据库进行管理的机制,为开发者提供无需编写原生SQL语句即可实现数据增、删、改、查等接口,同时开发者也可以直接运行原生SQL语句来满足复杂的场景需要。关系型数据库在应用卸载之后,才会被自动清除。

2 运作机制

RDB对外提供通用的接口,底层使用SQLite作为持久化存储引擎,支持SQLite具有的所有数据库特性。SQLite是一个进程内的库,具有自给自足、无服务、零配置、事务性特性的SQL数据库引擎。RDB包括但不限于事务、索引、视图、触发器、外键、参数化查询和预编译SQL语句。

3 使用场景

  • 通讯录
  • 记事本
  • 计算器历史记录
  • App用户登录信息
  • App主题
  • ...

4 流程

5 详细步骤

RDB对开发者提供的接口大部分为异步接口,均有callbackPromise两种返回形式,接下来将会一一介绍。

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两个参数,该方法有callbackPromise两种返回形式,如表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语句,有callbackPromise两种形式,如表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指定实例对象两种方式更新数据表中的数据,两种方式均有callbackPromise形式,如表5-6所示。

RdbPredicatesDataSharePredicates均用于数据表中用来代表数据实体的性质、特征或者数据实体之间关系的词项,主要用于定义数据表的操作条件。如设置根据账号查找用户信息的条件,或者根据账号修改用户密码的条件。两者区别在于使用前者需要先指定操作的数据表名称,同时前者为分布式数据操作做了扩充。使用后者需要导入新模块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也提供了RdbPredicatesDataSharePredicates两种方式,如表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数据库的简单使用做了讲解,其中涉及到RdbPredicatesDataSharePredicatesResultSet相关的更多内容将在后续封装RDB工具类中详细介绍。

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • 数据库
    +关注

    关注

    7

    文章

    3759

    浏览量

    64265
  • 关系型数据库

    关注

    0

    文章

    7

    浏览量

    2330
  • OpenHarmony
    +关注

    关注

    25

    文章

    3657

    浏览量

    16128
收藏 人收藏

    评论

    相关推荐

    OpenHarmony关系数据库查询结果呈现

    `ResultSet`(结果集)是OpenHarmony关系数据库提供查询数据表返回结果的方法,提供了多种灵活的
    的头像 发表于 03-28 18:06 1455次阅读
    <b class='flag-5'>OpenHarmony</b><b class='flag-5'>关系</b><b class='flag-5'>型</b><b class='flag-5'>数据库</b>查询结果呈现

    HarmonyOS开发案例:【关系数据库

    使用关系数据库的相关接口实现了对账单的增、删、改、查操作。
    的头像 发表于 04-22 14:58 622次阅读
    HarmonyOS开发案例:【<b class='flag-5'>关系</b><b class='flag-5'>型</b><b class='flag-5'>数据库</b>】

    HarmonyOS开发案例:【搭建关系数据库】(4)

    本节将介绍如何调用关系数据库接口在本地搭建数据库,并读写相应的用户数据
    的头像 发表于 05-11 10:27 751次阅读
    HarmonyOS开发案例:【搭建<b class='flag-5'>关系</b><b class='flag-5'>型</b><b class='flag-5'>数据库</b>】(4)

    关系数据库与非关系数据库的区别浅析

    关系数据库的一个劣势就是 阻抗失谐(impedance mismatch):关系模型和内存中的数据结构之间存在差异
    发表于 06-03 06:03

    HarmonyOS关系数据库和对象关系数据库的使用方法

    容易就上手的知识。本篇速成教程直接使用最精准和简短的文字,再配上讲解代码,让我们能在10分钟左右就能掌握最基本的数据库使用方法。数据库的三大要素:数据库、表、字段,接下来为大家介绍关系
    发表于 03-29 14:10

    什么是关系数据库

    什么是关系数据库 关系数据库简介   关系
    发表于 06-17 07:38 9119次阅读

    什么是非关系数据库

    什么是非关系数据库 谈到非关系数据库设计的难点,朱海峰说:“我们可以从一些场景来看这个问题
    发表于 06-17 15:49 3126次阅读

    关系数据库是什么?

    关系数据库是什么? 数字时代伊始,数据库就一直是商业计算的核心组成部分。事实上,关系数据库诞生于1970年。那一年,IBM的研究员E.F. Codd撰写了一篇论文,概述了主
    发表于 07-31 12:26 2198次阅读

    hbase和关系数据库的区别

    hbase和关系数据库的区别就是对于传统数据库,增加列对于一个项目来讲,改变是非常大的。但是对于nosql,插入列和删除列,跟传统数据库
    发表于 12-27 15:51 1.1w次阅读
    hbase和<b class='flag-5'>关系</b><b class='flag-5'>型</b><b class='flag-5'>数据库</b>的区别

    关系数据库表结构的设计有什么技巧?两个设计技巧详细说明

    关系数据库表结构的设计,有下面两个设计技巧: 物理主键作为关联的外键 关系数据库,由多个
    发表于 10-16 10:33 13次下载

    数据库学习入门资料之关系数据库标准语言SQL的详细资料概述

    本文档的主要内容详细介绍的是数据库学习入门资料之关系数据库标准语言SQL的详细资料概述主要内容包括了:1 SQL概述2 数据定义3 查询4
    发表于 10-25 16:29 20次下载

    数据库教程之关系数据库知识点总结的详细资料概述

    本文档的主要内容详细介绍的是数据库教程之关系数据库知识点总结的详细资料概述主要内容包括了:1 关系模型概述2
    发表于 11-28 19:44 4次下载
    <b class='flag-5'>数据库</b>教程之<b class='flag-5'>关系数据库</b>知识点总结的详细资料<b class='flag-5'>概述</b>

    基于SQLite的鸿蒙的关系数据库使用

    HarmonyOS关系数据库基于SQLite组件提供了一套完整的对本地数据库进行管理的机制,对外提供了一系列的增、删、改、查接口,也可以直接运行用户输入的SQL语句来满足复杂的场景需
    的头像 发表于 01-20 11:48 4016次阅读
    基于SQLite的鸿蒙的<b class='flag-5'>关系</b><b class='flag-5'>型</b><b class='flag-5'>数据库</b>使用

    轻松设计关系数据库教程

    本文讨论关系数据库设计相关的一些内容,涉及关系模型,表结构设计等内容,以学生选修课程讲述设计过程,在尽量讲清楚设计要领的前提下,简化设计内容。 本文基于MySQL数据库为基础,适合有一定关系
    的头像 发表于 07-13 09:13 1695次阅读

    关系数据库的基本原理(什么是关系数据库

    什么是关系数据库关系数据库,简称 RDBMS是由许多
    的头像 发表于 07-10 09:06 1372次阅读