鸿蒙开发笔记2
鸿蒙开发经验之谈~
·
经验1
在鸿蒙(HarmonyOS)的关系型数据库开发中,SQL查询语法遵循SQLite标准,以下是关键语法说明及注意事项:
1. 基础SELECT语法
SELECT 列名 FROM 表名 [WHERE 条件]
- 示例:
SELECT USER_ID FROM USERS WHERE ACCOUNT = ?USER_ID:目标列USERS:表名ACCOUNT = ?:条件(?为占位符)
2. 核心组件
(1) 占位符(?)
- 用于参数化查询,避免SQL注入
- 执行时需绑定实际值:
const queryArgs = ["user123"]; // 替换?的实际参数
(2) WHERE子句运算符
| 运算符 | 示例 | 说明 |
|---|---|---|
= |
ACCOUNT = ? |
等于 |
LIKE |
NAME LIKE '%张%' |
模糊匹配 |
IN |
ID IN (?,?,?) |
多值匹配 |
BETWEEN |
AGE BETWEEN 18 AND 30 |
范围查询 |
3. 鸿蒙执行流程
- 获取RdbStore实例(数据库连接)
- 构建查询参数:
const predicates = new relationalStore.RdbPredicates("USERS"); // 表名 predicates.equalTo("ACCOUNT", "user123"); // 条件设置 - 执行查询:
const resultSet = await rdbStore.query(predicates, ["USER_ID"]); // 指定返回列
4. 安全规范
- 禁止拼接SQL:
❌ 错误示例:SELECT ... WHERE ACCOUNT = '${userInput}'
✅ 正确做法:始终使用占位符?绑定参数 - 列名/表名验证:动态名称需白名单过滤
5. 高级查询
-- 多表JOIN
SELECT u.USER_ID, o.ORDER_NO
FROM USERS u
JOIN ORDERS o ON u.ID = o.USER_ID
WHERE u.ACCOUNT = ?
-- 聚合函数
SELECT COUNT(*) FROM USERS WHERE AGE > 18
提示:完整文档见 HarmonyOS RDB开发指南(官方Gitee仓库)
经验2
在鸿蒙(HarmonyOS)的关系型数据库中清空数据表的所有数据后,通常需要手动重置主键自增计数器。以下是详细分析和操作建议,基于鸿蒙数据库的设计机制和最佳实践:
1. 为什么需要重置主键自增计数器?
- 计数器不自动重置:鸿蒙的关系型数据库基于 SQLite 实现。当使用
DELETE操作清空表数据时(例如rdbStore.delete(predicates)),数据库仅移除数据行,但主键的自增计数器(如AUTOINCREMENT)会保留最后一次插入的 ID 值。下次插入数据时,主键会从旧的最大值继续递增,可能导致主键冲突或不连续。 - 潜在风险:
- 如果后续插入数据时主键值重复,会触发唯一性约束错误(错误码 14800011)。
- 在数据同步或备份场景中,主键不连续可能影响数据一致性。
2. 如何重置主增计数器?
在鸿蒙开发中,需通过执行自定义 SQL 语句手动重置计数器。以下是具体方法(以 ArkTS 为例):
步骤 1:清空表数据
使用 RdbPredicates 删除所有数据:
import relationalStore from '@kit.RelationalStore';
// 假设 rdbStore 已初始化
let predicates = new relationalStore.RdbPredicates('your_table_name');
await rdbStore.delete(predicates); // 清空表数据
步骤 2:重置自增计数器
执行 SQL 语句重置计数器:
// 重置主键计数器(针对 SQLite 实现)
await rdbStore.executeSql("DELETE FROM sqlite_sequence WHERE name = 'your_table_name';");
- 说明:
sqlite_sequence是 SQLite 的系统表,存储每个表的自增计数器值。- 执行此语句后,主键将从
1重新开始计数。
3. 注意事项
- 表是否定义自增主键:仅当表的主键使用了
AUTOINCREMENT属性时(例如通过@Column({ autoIncrement: true })注解),才需此操作。非自增主键无需重置。 - 原子性操作:建议将清空数据和重置计数器放在事务中,确保操作原子性:
await rdbStore.beginTransaction(); try { await rdbStore.delete(predicates); await rdbStore.executeSql("DELETE FROM sqlite_sequence WHERE name = 'your_table_name';"); await rdbStore.commit(); } catch (err) { await rdbStore.rollback(); console.error(`Operation failed: ${err.code}, ${err.message}`); } - 替代方案:如果表结构允许,可删除并重建表(通过
rdbStore.executeSql('DROP TABLE ...')和重新初始化),但此方法更重,适用于表结构需变更的场景。
4. 使用第三方库的说明
如果使用 ZDbUtil 等第三方库(参考搜索结果中的库),其默认的 delete 或 batchDelete 操作不会自动重置计数器。需手动调用原生 executeSql 方法完成重置,或检查库是否提供扩展接口(如自定义 SQL 执行功能)。
总结
| 操作 | 是否必需 | 原因 | 推荐方法 |
|---|---|---|---|
| 清空表数据 | 是 | 移除所有数据行 | rdbStore.delete(predicates) |
| 重置自增计数器 | 是 | 避免主键冲突和连续性错误 | rdbStore.executeSql("DELETE FROM sqlite_sequence WHERE name = 'table_name';") |
通过手动重置计数器,可确保数据表在清空后保持正确的初始状态。如果涉及复杂业务逻辑(如数据同步),建议在鸿蒙的 relationalStore 模块文档中进一步查阅事务管理和错误处理机制。
更多推荐

所有评论(0)