HarmonyOS鸿蒙Next中ArkData数据库备份出错,Sqlite3包含虚拟字段时不能备份数据库

HarmonyOS鸿蒙Next中ArkData数据库备份出错,Sqlite3包含虚拟字段时不能备份数据库 我在APP中进行数据库备份操作出现报错(store.backup),经过报错信息和调试分析,原因是数据表中存在虚拟字段就不能备份,删除含有虚拟字段的数据表就可以成功备份。

环境信息:真机和模拟器都报错

数据库版本:3.44.4

系统版本:6.0.2

实测5.0 API 12以上所有版本都出错。

执行代码片段为:

store?.backup(`backup_${AnnConstant.ANN_DB_NAME}`)
                      .then(result => {
                        // AnnNotifyUtil.Toast("备份成功")
                        AnnNotifyUtil.dialog(this.getUIContext(), "备份成功")
                      })
                      .catch((error: BusinessError) => {
                        console.error('备份失败', error)
                        AnnNotifyUtil.toast("备份失败")
                      })

报错信息如下: cke_589.png

含有虚拟字段数据表DDL如下:

CREATE TABLE ann_xxxxx_category
(
    id                   INTEGER PRIMARY KEY AUTOINCREMENT,
    create_time          TEXT        NOT NULL default (strftime('%Y-%m-%dT%H:%M:%fZ', 'now')),
    update_time          TEXT        NOT NULL default (strftime('%Y-%m-%dT%H:%M:%fZ', 'now')),
    subject_type         VARCHAR(32) NULL,               -- 项目类型
    name                 VARCHAR(32) NOT NULL,           -- 类目名称
    type                 VARCHAR(32) NOT NULL,           -- income/expense/transfer (收入/支出/转账)
    code                 VARCHAR(64),                    -- 代码
    icon                 VARCHAR(255),                   -- 图标名称/路径
    color                VARCHAR(32),                    -- 颜色代码
    parent_id            INTEGER              default 0, -- 父级类目ID,支持多级分类
    remark               VARCHAR(255),                   -- 备注
    sort_order           INTEGER              DEFAULT 0, -- 排序(数字越大越靠前,内置数据可用使用负数值,排序越靠后的可用绝对值越大的负数值)
    is_built_in          INTEGER              DEFAULT 0, -- 是否为系统预设(0=否,1=是)
    is_enabled           INTEGER              DEFAULT 1, -- 是否启用(0=禁用,1=启用)
    user_id              INTEGER              DEFAULT 1, -- 用户id
    act_user_id          INTEGER              DEFAULT 1, -- 操作用户ID
    -- 虚拟字段,用于唯一索引
    subject_type_virtual VARCHAR(32) GENERATED ALWAYS AS (COALESCE(subject_type, '')) STORED,
    parent_id_virtual    INTEGER GENERATED ALWAYS AS (COALESCE(parent_id, -1)) STORED,
    unique (code),
    unique (subject_type_virtual, parent_id_virtual, type, name)
);

更多关于HarmonyOS鸿蒙Next中ArkData数据库备份出错,Sqlite3包含虚拟字段时不能备份数据库的实战教程也可以访问 https://www.itying.com/category-93-b0.html

3 回复

开发者您好,经确认,sqlite包含虚拟字段时不能备份数据库,如果不满足您的诉求,麻烦提供如下信息:请问您是在什么样的业务场景中使用该能力,交互流程是怎样的,在哪一个环节遇到了问题?方便说明能力不满足可能带来的影响:什么时间用到?是否高频?有无三方库可以做到?若提供该能力,是否会造成大工作量返工?请您注意提供的内容不要包含您或第三方的非公开信息,如给您带来不便,敬请谅解。

更多关于HarmonyOS鸿蒙Next中ArkData数据库备份出错,Sqlite3包含虚拟字段时不能备份数据库的实战系列教程也可以访问 https://www.itying.com/category-93-b0.html


鸿蒙Next中ArkData使用Sqlite3备份数据库时,若表包含虚拟字段(VIRTUAL),备份操作会失败。这是因为Sqlite3的备份API在默认情况下不支持虚拟表或包含虚拟字段的表。

这是一个已知的ArkData备份限制。在HarmonyOS Next中,store.backup() 方法底层调用SQLite的备份API,而SQLite的备份机制在处理包含STORED虚拟字段的表时存在兼容性问题。

问题根源: SQLite的 sqlite3_backup_init() API 在备份包含生成列(GENERATED ALWAYS AS … STORED)的表时,可能会因内部架构解析差异导致失败。你DDL中的 subject_type_virtualparent_id_virtual 正是这种STORED虚拟字段。

临时解决方案(二选一):

  1. 修改表结构,移除虚拟字段:将虚拟字段的逻辑移到应用层或使用触发器实现。例如,将唯一索引改为:

    CREATE UNIQUE INDEX idx_unique_category ON ann_xxxxx_category (
      COALESCE(subject_type, ''),
      COALESCE(parent_id, -1),
      type,
      name
    );
    

    删除 subject_type_virtualparent_id_virtual 两个字段的定义。

  2. 使用手动备份替代 store.backup():通过执行 SELECT * FROM ... 查询所有数据,并将结果集序列化到本地文件(如JSON)。恢复时解析文件并执行INSERT操作。这种方式绕过SQLite备份API,但需要自行处理事务和表结构。

长期建议: 如果应用必须保留STORED虚拟字段,目前需避免使用ArkData的备份接口。可关注HarmonyOS后续版本更新,看是否在API 15或更高版本中修复此兼容性问题。

回到顶部