1# RelationalStore开发指导 (C/C++)
2
3
4## 场景介绍
5
6RelationalStore提供了一套完整的对本地数据库进行管理的机制,对外提供了一系列的增、删、改、查等接口,也可以直接运行用户输入的SQL语句来满足复杂的场景需要。
7
8
9## 基本概念
10
11- **谓词**:数据库中用来代表数据实体的性质、特征或者数据实体之间关系的词项,主要用来定义数据库的操作条件。
12
13- **结果集**:指用户查询之后的结果集合,可以对数据进行访问。结果集提供了灵活的数据访问方式,可以更方便地拿到用户想要的数据。
14
15
16## 约束限制
17
18- 系统默认日志方式是WAL(Write Ahead Log)模式,系统默认落盘方式是FULL模式。
19
20- 数据库中连接池的最大数量是4个,用以管理用户的读操作。
21
22- 为保证数据的准确性,数据库同一时间只能支持一个写操作。
23
24- 当应用被卸载完成后,设备上的相关数据库文件及临时文件会被自动清除。
25
26- 使用API11新增的端云同步等接口时,需要确保已实现云服务功能。
27
28
29## 接口说明
30
31详细的接口说明请参考[RDB](../reference/apis-arkdata/_r_d_b.md)。
32
33| 接口名称 | 描述 |
34| -------- | -------- |
35| OH_Rdb_GetOrOpen(const OH_Rdb_Config *config, int *errCode) | 获得一个相关的OH_Rdb_Store实例,操作关系型数据库。 |
36| OH_Rdb_Execute(OH_Rdb_Store *store, const char *sql) | 执行包含指定参数但不返回值的SQL语句。 |
37| OH_Rdb_Insert(OH_Rdb_Store *store, const char *table, OH_VBucket *valuesBucket) | 向目标表中插入一行数据。 |
38| OH_Rdb_Update(OH_Rdb_Store *store, OH_VBucket *valuesBucket, OH_Predicates *predicates) | 根据OH_Predicates的指定实例对象更新数据库中的数据。 |
39| OH_Rdb_Delete(OH_Rdb_Store *store, OH_Predicates *predicates) | 根据OH_Predicates的指定实例对象从数据库中删除数据。 |
40| OH_Rdb_Query(OH_Rdb_Store *store, OH_Predicates *predicates, const char *const *columnNames, int length) | 根据指定条件查询数据库中的数据。 |
41| OH_Rdb_DeleteStore(const OH_Rdb_Config *config) | 删除数据库。 |
42| OH_VBucket_PutAsset(OH_VBucket *bucket, const char *field, Rdb_Asset *value) | 把Rdb_Asset类型的数据放到指定的OH_VBucket对象中。 |
43| OH_VBucket_PutAssets(OH_VBucket *bucket, const char *field, Rdb_Asset *value, uint32_t count) | 把Rdb_Asset数组类型的数据放到指定的OH_VBucket对象中。 |
44| OH_Rdb_SetDistributedTables(OH_Rdb_Store *store, const char *tables[], uint32_t count, Rdb_DistributedType type, const Rdb_DistributedConfig *config) | 设置分布式数据库表。 |
45| OH_Rdb_FindModifyTime(OH_Rdb_Store *store, const char *tableName, const char *columnName, OH_VObject *values) | 获取数据库指定表中指定列的数据的最后修改时间。 |
46| OH_Rdb_CloudSync(OH_Rdb_Store *store, Rdb_SyncMode mode, const char *tables[], uint32_t count, const Rdb_ProgressObserver *observer) | 手动执行对指定表的端云同步,使用该接口需要实现云服务功能。 |
47| int OH_Data_Asset_SetName(Data_Asset *asset, const char *name) | 为资产类型数据设置名称。 |
48| int OH_Data_Asset_SetUri(Data_Asset *asset, const char *uri) | 为资产类型数据设置绝对路径。 |
49| int OH_Data_Asset_SetPath(Data_Asset *asset, const char *path) | 为资产类型数据设置应用沙箱里的相对路径。 |
50| int OH_Data_Asset_SetCreateTime(Data_Asset *asset, int64_t createTime) | 为资产类型数据设置创建时间。 |
51| int OH_Data_Asset_SetModifyTime(Data_Asset *asset, int64_t modifyTime) | 为资产类型数据设置最后修改时间。 |
52| int OH_Data_Asset_SetSize(Data_Asset *asset, size_t size) | 为资产类型数据设置占用空间大小。 |
53| int OH_Data_Asset_SetStatus(Data_Asset *asset, Data_AssetStatus status) | 为资产类型数据设置状态码。 |
54| int OH_Data_Asset_GetName(Data_Asset *asset, char *name, size_t *length) | 获取资产类型数据的名称。 |
55| int OH_Data_Asset_GetUri(Data_Asset *asset, char *uri, size_t *length) | 获取资产类型数据的绝对路径。 |
56| int OH_Data_Asset_GetPath(Data_Asset *asset, char *path, size_t *length) | 获取资产类型数据在应用沙箱内的相对路径。 |
57| int OH_Data_Asset_GetCreateTime(Data_Asset *asset, int64_t *createTime) | 获取资产类型数据的创建时间。 |
58| int OH_Data_Asset_GetModifyTime(Data_Asset *asset, int64_t *modifyTime) | 获取资产类型数据的最后修改时间。 |
59| int OH_Data_Asset_GetSize(Data_Asset *asset, size_t *size) | 获取资产类型数据的占用空间大小。 |
60| int OH_Data_Asset_GetStatus(Data_Asset *asset, Data_AssetStatus *status) | 获取资产类型数据的状态码。 |
61| Data_Asset *OH_Data_Asset_CreateOne() | 创造一个资产类型实例。使用完毕后需要调用OH_Data_Asset_DestroyOne释放内存。 |
62| int OH_Data_Asset_DestroyOne(Data_Asset *asset) | 销毁一个资产类型实例并回收内存。 |
63| Data_Asset **OH_Data_Asset_CreateMultiple(uint32_t count) | 创造指定数量的资产类型实例。使用完毕后需要调用OH_Data_Asset_DestroyMultiple释放内存。 |
64| int OH_Data_Asset_DestroyMultiple(Data_Asset **assets, uint32_t count) | 销毁指定数量的资产类型实例并回收内存。 |
65| int OH_Rdb_Subscribe(OH_Rdb_Store *store, Rdb_SubscribeType type, const Rdb_DataObserver *observer) | 为数据库注册观察者, 当分布式数据库中的数据发生更改时,将调用回调。 |
66| int OH_Rdb_Unsubscribe(OH_Rdb_Store *store, Rdb_SubscribeType type, const Rdb_DataObserver *observer) | 从数据库中删除指定类型的指定观察者。 |
67| int OH_Rdb_SubscribeAutoSyncProgress(OH_Rdb_Store *store, const Rdb_ProgressObserver *observer) | 订阅RDB存储的自动同步进程, 当收到自动同步进度的通知时,将调用回调。 |
68| int OH_Rdb_UnsubscribeAutoSyncProgress(OH_Rdb_Store *store, const Rdb_ProgressObserver *observer) | 取消订阅RDB存储的自动同步进程。 |
69
70
71## 开发步骤
72
73**添加动态链接库**
74
75CMakeLists.txt中添加以下lib。
76
77```txt
78libnative_rdb_ndk.z.so
79```
80
81**头文件**
82
83```c++
84#include <database/data/data_asset.h>
85#include <database/rdb/oh_cursor.h>
86#include <database/rdb/oh_predicates.h>
87#include <database/rdb/oh_value_object.h>
88#include <database/rdb/oh_values_bucket.h>
89#include <database/rdb/relational_store.h>
90#include <database/rdb/relational_store_error_code.h>
91```
92
931. 获取OH_Rdb_Store实例,创建数据库文件。其中dataBaseDir变量为应用沙箱路径,Stage模式下建议使用数据库目录,参考[Context](../reference/apis-ability-kit/js-apis-inner-application-context.md)的databaseDir属性。FA模式下,由于没有接口获取数据库沙箱路径,可使用应用程序的文件目录,可参考[Context](../reference/apis-ability-kit/js-apis-inner-app-context.md)的getFilesDir接口。area为数据库文件存放的安全区域,详见[contextConstant](../reference/apis-ability-kit/js-apis-app-ability-contextConstant.md),开发时需要实现由AreaMode枚举值对Rdb_SecurityArea枚举值的转换。示例代码如下所示:
94
95   ```c
96   // 创建OH_Rdb_Config对象
97   OH_Rdb_Config config;
98   // 该路径为应用沙箱路径
99   config.dataBaseDir = "xxx";
100   // 数据库文件名
101   config.storeName = "RdbTest.db";
102   // 应用包名
103   config.bundleName = "xxx";
104   // 应用模块名
105   config.moduleName = "xxx";
106   // 数据库文件安全等级
107   config.securityLevel = OH_Rdb_SecurityLevel::S3;
108   // 数据库是否加密
109   config.isEncrypt = false;
110   // config所占内存大小
111   config.selfSize = sizeof(OH_Rdb_Config);
112   // 数据库文件存放的安全区域
113   config.area = RDB_SECURITY_AREA_EL1;
114
115   int errCode = 0;
116   // 获取OH_Rdb_Store实例
117   OH_Rdb_Store *store_ = OH_Rdb_GetOrOpen(&config, &errCode);
118   ```
119
1202. 获取到OH_Rdb_Store后,调用OH_Rdb_Execute接口创建表,并调用OH_Rdb_Insert接口插入数据。示例代码如下所示:
121
122   ```c
123   char createTableSql[] = "CREATE TABLE IF NOT EXISTS EMPLOYEE (ID INTEGER PRIMARY KEY AUTOINCREMENT, NAME TEXT NOT NULL, "
124                           "AGE INTEGER, SALARY REAL, CODES BLOB)";
125   // 执行建表语句
126   OH_Rdb_Execute(store_, createTableSql);
127
128   // 创建键值对实例
129   OH_VBucket *valueBucket = OH_Rdb_CreateValuesBucket();
130   valueBucket->putText(valueBucket, "NAME", "Lisa");
131   valueBucket->putInt64(valueBucket, "AGE", 18);
132   valueBucket->putReal(valueBucket, "SALARY", 100.5);
133   uint8_t arr[] = {1, 2, 3, 4, 5};
134   int len = sizeof(arr) / sizeof(arr[0]);
135   valueBucket->putBlob(valueBucket, "CODES", arr, len);
136   // 插入数据
137   int rowId = OH_Rdb_Insert(store_, "EMPLOYEE", valueBucket);
138   // 销毁键值对实例
139   valueBucket->destroy(valueBucket);
140   ```
141
142   > **说明:**
143   >
144   > 关系型数据库没有显式的flush操作实现持久化,数据插入即保存在持久化文件。
145
1463. 根据谓词指定的实例对象,对数据进行修改或删除。
147
148   调用OH_Rdb_Update方法修改数据,调用OH_Rdb_Delete方法删除数据。示例代码如下所示:
149
150   ```c
151   // 修改数据
152   OH_VBucket *valueBucket = OH_Rdb_CreateValuesBucket();
153   valueBucket->putText(valueBucket, "NAME", "Rose");
154   valueBucket->putInt64(valueBucket, "AGE", 22);
155   valueBucket->putReal(valueBucket, "SALARY", 200.5);
156   uint8_t arr[] = {1, 2, 3, 4, 5};
157   int len = sizeof(arr) / sizeof(arr[0]);
158   valueBucket->putBlob(valueBucket, "CODES", arr, len);
159
160   OH_Predicates *predicates = OH_Rdb_CreatePredicates("EMPLOYEE");
161   OH_VObject *valueObject = OH_Rdb_CreateValueObject();
162   const char *name = "Lisa";
163   valueObject->putText(valueObject, name);
164   predicates->equalTo(predicates, "NAME", valueObject)->andOperate(predicates);
165   uint32_t count = 1;
166   double salary = 100.5;
167   valueObject->putDouble(valueObject, &salary, count);
168   predicates->equalTo(predicates, "SALARY", valueObject);
169
170   int changeRows = OH_Rdb_Update(store_, valueBucket, predicates);
171   valueObject->destroy(valueObject);
172   valueBucket->destroy(valueBucket);
173   predicates->destroy(predicates);
174   ```
175
176   ```c
177   // 删除数据
178   OH_Predicates *predicates = OH_Rdb_CreatePredicates("EMPLOYEE");
179   OH_VObject *valueObject = OH_Rdb_CreateValueObject();
180   const char *name = "Lisa";
181   valueObject->putText(valueObject, name);
182   predicates->equalTo(predicates, "NAME", valueObject);
183   int deleteRows = OH_Rdb_Delete(store_, predicates);
184   valueObject->destroy(valueObject);
185   predicates->destroy(predicates);
186   ```
187
1884. 根据谓词指定的查询条件查找数据。
189
190   调用OH_Rdb_Query方法查找数据,返回一个OH_Cursor结果集。示例代码如下所示:
191
192   ```c
193   OH_Predicates *predicates = OH_Rdb_CreatePredicates("EMPLOYEE");
194
195   const char *columnNames[] = {"NAME", "AGE"};
196   int len = sizeof(columnNames) / sizeof(columnNames[0]);
197   OH_Cursor *cursor = OH_Rdb_Query(store_, predicates, columnNames, len);
198
199   int columnCount = 0;
200   cursor->getColumnCount(cursor, &columnCount);
201
202   // OH_Cursor是一个数据集合的游标,默认指向第-1个记录,有效的数据从0开始
203   int64_t age;
204   while (cursor->goToNextRow(cursor) == OH_Rdb_ErrCode::RDB_OK) {
205       cursor->getInt64(cursor, 1, &age);
206   }
207
208   // 释放谓词实例
209   predicates->destroy(predicates);
210   // 释放结果集
211   cursor->destroy(cursor);
212   ```
213
2145. 向数据库表中插入资产类型数据。
215
216   ```c
217   // 列的属性为单个资产类型时,sql语句中应指定为asset,多个资产类型应指定为assets。
218   char createAssetTableSql[] = "CREATE TABLE IF NOT EXISTS asset_table (id INTEGER PRIMARY KEY AUTOINCREMENT, data1 asset, data2 assets );";
219   errCode = OH_Rdb_Execute(store_, createAssetTableSql);
220   Data_Asset *asset = OH_Data_Asset_CreateOne();
221   OH_Data_Asset_SetName(asset, "name0");
222   OH_Data_Asset_SetUri(asset, "uri0");
223   OH_Data_Asset_SetPath(asset, "path0");
224   OH_Data_Asset_SetCreateTime(asset, 1);
225   OH_Data_Asset_SetModifyTime(asset, 1);
226   OH_Data_Asset_SetSize(asset, 1);
227   OH_Data_Asset_SetStatus(asset, Data_AssetStatus::ASSET_NORMAL);
228   errCode = OH_VBucket_PutAsset(valueBucket, "data1", asset);
229
230   Data_Asset **assets = OH_Data_Asset_CreateMultiple(2);
231
232   OH_Data_Asset_SetName(assets[0], "name0");
233   OH_Data_Asset_SetUri(assets[0], "uri0");
234   OH_Data_Asset_SetPath(assets[0], "path0");
235   OH_Data_Asset_SetCreateTime(assets[0], 1);
236   OH_Data_Asset_SetModifyTime(assets[0], 1);
237   OH_Data_Asset_SetSize(assets[0], 1);
238   OH_Data_Asset_SetStatus(assets[0], Data_AssetStatus::ASSET_NORMAL);
239
240   OH_Data_Asset_SetName(assets[1], "name1");
241   OH_Data_Asset_SetUri(assets[1], "uri1");
242   OH_Data_Asset_SetPath(assets[1], "path1");
243   OH_Data_Asset_SetCreateTime(assets[1], 1);
244   OH_Data_Asset_SetModifyTime(assets[1], 1);
245   OH_Data_Asset_SetSize(assets[1], 1);
246   OH_Data_Asset_SetStatus(assets[1], Data_AssetStatus::ASSET_NORMAL);
247
248   errCode = OH_VBucket_PutAssets(valueBucket, "data2", assets, assetsCount);
249   int rowID = OH_Rdb_Insert(cursorTestRdbStore_, table, valueBucket);
250   // 释放Data_Asset*和Data_Asset**
251   OH_Data_Asset_DestroyMultiple(assets, 2);
252   OH_Data_Asset_DestroyOne(asset);
253   ```
254
2556. 从结果集中读取资产类型数据。
256
257   ```c
258   OH_Predicates *predicates = OH_Rdb_CreatePredicates("asset_table");
259
260   OH_Cursor *cursor = OH_Rdb_Query(cursorTestRdbStore_, predicates, NULL, 0);
261   cursor->goToNextRow(cursor);
262
263   uint32_t assetCount = 0;
264   // assetCount作为出参获取该列资产类型数据的数量
265   errCode = cursor->getAssets(cursor, 2, nullptr, &assetCount);
266   Data_Asset **assets = OH_Data_Asset_CreateMultiple(assetCount);
267   errCode = cursor->getAssets(cursor, 2, assets, &assetCount);
268   Data_Asset *asset = assets[1];
269
270   char name[10] = "";
271   size_t nameLength = 10;
272   errCode = OH_Data_Asset_GetName(asset, name, &nameLength);
273
274   char uri[10] = "";
275   size_t uriLength = 10;
276   errCode = OH_Data_Asset_GetUri(asset, uri, &uriLength);
277
278   char path[10] = "";
279   size_t pathLength = 10;
280   errCode = OH_Data_Asset_GetPath(asset, path, &pathLength);
281
282   int64_t createTime = 0;
283   errCode = OH_Data_Asset_GetCreateTime(asset, &createTime);
284
285   int64_t modifyTime = 0;
286   errCode = OH_Data_Asset_GetModifyTime(asset, &modifyTime);
287
288   size_t size = 0;
289   errCode = OH_Data_Asset_GetSize(asset, &size);
290
291   Data_AssetStatus status = Data_AssetStatus::ASSET_NULL;
292   errCode = OH_Data_Asset_GetStatus(asset, &status);
293
294   predicates->destroy(predicates);
295   OH_Data_Asset_DestroyMultiple(assets, assetCount);
296   cursor->destroy(cursor);
297   ```
298
2997. 查询数据的最后修改时间。调用OH_Rdb_FindModifyTime查询指定表中指定列的数据的最后修改时间,该接口返回一个有两列数据的OH_Cursor对象,第一列为传入的主键/RowId,第二列为最后修改时间。示例代码如下所示:
300
301   ```c
302   OH_VObject *values = OH_Rdb_CreateValueObject();
303   int64_t keys[] = { 1 };
304   values->putInt64(values, keys, 1);
305   OH_Cursor *cursor;
306   cursor = OH_Rdb_FindModifyTime(store_, "EMPLOYEE", "ROWID", values);
307   ```
308
3098. 创建分布式表。调用OH_Rdb_Execute接口创建表之后,可以将已创建的表设置成分布式表,并配置相关的分布式选项。使用该接口需要实现云服务功能。示例代码如下所示:
310
311   ```c
312   constexpr int TABLE_COUNT = 1;
313   const char *table[TABLE_COUNT];
314   table[0] = "EMPLOYEE";
315   int errcode = OH_Rdb_SetDistributedTables(store_, table, TABLE_COUNT, Rdb_DistributedType::DISTRIBUTED_CLOUD, &config);
316   ```
317
3189. 对分布式表手动执行端云同步。调用OH_Rdb_SetDistributedTables创建分布式表之后,可以对该表进行手动端云同步。使用该接口需要实现云服务功能。示例代码如下所示:
319
320    ```c
321   // 定义回调函数
322   void CloudSyncObserverCallback(void *context, Rdb_ProgressDetails *progressDetails)
323   {
324    // do something
325   }
326   const Rdb_ProgressObserver observer = { .context = nullptr, .callback = CloudSyncObserverCallback };
327   OH_Rdb_CloudSync(store_, Rdb_SyncMode::SYNC_MODE_TIME_FIRST, table, TABLE_COUNT, &observer);
328   ```
329
33010. 将数据观察者注册到指定的存储对象(store)上,并订阅指定类型(type)的事件。在数据发生变化时,系统会调用相应的回调函数来处理进度观察。调用OH_Rdb_Subscribe接口订阅数据变化事件。使用该接口需要实现云服务功能。示例代码如下所示:
331
332    ```c
333    // 定义回调函数
334    void RdbSubscribeBriefCallback(void *context, const char *values[], uint32_t count)
335    {
336    // do something
337    }
338    Rdb_BriefObserver briefObserver;
339    const Rdb_BriefObserver briefObserver = { .context = nullptr, .callback = RdbSubscribeBriefCallback };
340    // 订阅数据变化
341    OH_Rdb_Subscribe(store_, Rdb_SubscribeType::RDB_SUBSCRIBE_TYPE_CLOUD, &briefObserver);
342    ```
343
344    调用OH_Rdb_Subscribe接口订阅本地数据库数据变更的事件。示例代码如下所示:
345
346    ```c
347    // 定义回调函数
348    void LocalDataChangeObserverCallback1(void *context, const Rdb_ChangeInfo **changeInfo, uint32_t count)
349    {
350       for (uint32_t i = 0; i < count; i++) {
351          EXPECT_EQ(DISTRIBUTED_CHANGE_INFO_VERSION, changeInfo[i]->version);
352          // 表名为employee
353          changeInfo[i]->tableName;
354          changeInfo[i]->ChangeType;
355          // 添加行数为1
356          changeInfo[i]->inserted.count;
357          // 修改行数为0
358          changeInfo[i]->updated.count;
359          // 删除行数为0
360          changeInfo[i]->deleted.count;
361       }
362    }
363    Rdb_DetailsObserver callback = LocalDataChangeObserverCallback1;
364    Rdb_DataObserver observer = { nullptr, { callback } };
365    // 订阅本地数据库数据变更的事件
366    OH_Rdb_Subscribe(store_, Rdb_SubscribeType::RDB_SUBSCRIBE_TYPE_LOCAL_DETAILS, &observer);
367
368    OH_VBucket* valueBucket = OH_Rdb_CreateValuesBucket();
369    valueBucket->putText(valueBucket, "NAME", "Lisa");
370    valueBucket->putInt64(valueBucket, "AGE", 18);
371    valueBucket->putReal(valueBucket, "SALARY", 100.5);
372    uint8_t arr[] = {1, 2, 3, 4, 5};
373    int len = sizeof(arr) / sizeof(arr[0]);
374    valueBucket->putBlob(valueBucket, "CODES", arr, len);
375    // 插入数据
376    int rowId = OH_Rdb_Insert(store_, "EMPLOYEE", valueBucket);
377    // 销毁键值对实例
378    valueBucket->destroy(valueBucket);
379    ```
380
38111. 从指定的存储对象(store)中取消对指定类型(type)的事件的订阅。取消后,系统将不再调用相应的回调函数来处理进度观察。调用OH_Rdb_Unsubscribe接口取消订阅数据变化事件。使用该接口需要实现云服务功能。示例代码如下所示:
382
383    ```c
384    // 定义回调函数
385    void RdbSubscribeBriefCallback(void *context, const char *values[], uint32_t count)
386    {
387    // do something
388    }
389    Rdb_BriefObserver briefObserver = RdbSubscribeBriefCallback;
390    const Rdb_DataObserver briefObs = { .context = nullptr, .callback.briefObserver = briefObserver };
391    // 取消订阅数据变化事件
392    OH_Rdb_Unsubscribe(store_, Rdb_SubscribeType::RDB_SUBSCRIBE_TYPE_CLOUD, &briefObs);
393    ```
394    调用OH_Rdb_Unsubscribe接口取消订阅本地数据库数据变更的事件。示例代码如下所示:
395    ```c
396    // 定义回调函数
397    void LocalDataChangeObserverCallback1(void *context, const Rdb_ChangeInfo **changeInfo, uint32_t count)
398    {
399    // do something
400    }
401    Rdb_DetailsObserver callback = LocalDataChangeObserverCallback1;
402    Rdb_DataObserver observer = { nullptr, { callback } };
403    // 取消订阅本地数据库数据变更的事件
404    OH_Rdb_Unsubscribe(store_, Rdb_SubscribeType::RDB_SUBSCRIBE_TYPE_LOCAL_DETAILS, &observer);
405    ```
406
407
40812. 将进度观察者注册到指定的存储对象(store)上,以便订阅自动同步进度的事件。当存储对象进行自动同步时,系统会调用相应的回调函数处理进度观察。调用OH_Rdb_SubscribeAutoSyncProgress接口订阅自动同步进度事件。使用该接口需要实现云服务功能。示例代码如下所示:
409
410    ```c
411    // 定义回调函数
412    void RdbProgressObserverCallback(void *context, Rdb_ProgressDetails *progressDetails)
413    {
414    // do something
415    }
416    const Rdb_ProgressObserver observer = { .context = nullptr, .callback = RdbProgressObserverCallback };
417    OH_Rdb_SubscribeAutoSyncProgress(store_, &observer);
418    ```
419
42013. 从指定的存储对象(store)中取消订阅自动同步进度的事件。取消后,系统将不再调用相应的回调函数来处理进度观察。调用OH_Rdb_UnsubscribeAutoSyncProgress接口取消订阅自动同步进度事件。使用该接口需要实现云服务功能。示例代码如下所示:
421
422    ```c
423    // 定义回调函数
424    void RdbProgressObserverCallback(void *context, Rdb_ProgressDetails *progressDetails)
425    {
426    // do something
427    }
428    const Rdb_ProgressObserver observer = { .context = nullptr, .callback = RdbProgressObserverCallback };
429    OH_Rdb_UnsubscribeAutoSyncProgress(store_, &observer);
430    ```
431
43214. 删除数据库。调用OH_Rdb_DeleteStore方法,删除数据库及数据库相关文件。示例代码如下:
433
434    ```c
435    // 释放数据库实例
436    OH_Rdb_CloseStore(store_);
437    // 删除数据库文件
438    OH_Rdb_DeleteStore(&config);
439    ```
440
441
442
443
444
445
446