database-relational-guidelines.md 25.4 KB
Newer Older
A
annie_wangli 已提交
1
# RDB Development
Z
zengyawen 已提交
2

A
annie_wangli 已提交
3
## When to Use
Z
zengyawen 已提交
4

A
Annie_wang 已提交
5
A relational database (RDB) store allows you to operate local data with or without native SQL statements based on SQLite.
Z
zengyawen 已提交
6

A
annie_wangli 已提交
7 8

## Available APIs
Z
zengyawen 已提交
9

A
Annie_wang 已提交
10
Most of the RDB store APIs are asynchronous interfaces, which can use a callback or promise to return the result. This document uses the promise-based APIs as an example. For more information about the APIs, see [RDB Store](../reference/apis/js-apis-data-relationalStore.md).
A
Annie_wang 已提交
11

A
annie_wangli 已提交
12
### Creating or Deleting an RDB Store
Z
zengyawen 已提交
13

A
Annie_wang 已提交
14
The following table describes the APIs for creating and deleting an RDB store.
Z
zengyawen 已提交
15

A
annie_wangli 已提交
16 17
**Table 1** APIs for creating and deleting an RDB store

A
Annie_wang 已提交
18 19
| API                                                      | Description                                                        |
| ------------------------------------------------------------ | ------------------------------------------------------------ |
A
Annie_wang 已提交
20 21
| getRdbStore(context: Context, config: StoreConfig): Promise&lt;RdbStore&gt; | Obtains an **RdbStore** object. This API uses a promise to return the result. You can set parameters for the **RdbStore** object based on service requirements and use **RdbStore** APIs to perform data operations.<br>- **context**: application context.<br>- **config**: configuration of the RDB store.|
| deleteRdbStore(context: Context, name: string): Promise&lt;void&gt; | Deletes an RDB store. This API uses a promise to return the result.<br>- **context**: application context.<br>- **name**: name of the RDB store to delete.|
Z
zengyawen 已提交
22

A
annie_wangli 已提交
23
### Managing Data in an RDB Store
Z
zengyawen 已提交
24

A
annie_wangli 已提交
25 26
The RDB provides APIs for inserting, deleting, updating, and querying data in the local RDB store.

A
Annie_wang 已提交
27
- **Inserting Data**
A
annie_wangli 已提交
28
  
A
annie_wangli 已提交
29
  The RDB provides APIs for inserting data through a **ValuesBucket** in a data table. If the data is inserted, the row ID of the data inserted will be returned; otherwise, **-1** will be returned.
A
annie_wangli 已提交
30
  
A
Annie_wang 已提交
31
  **Table 2** API for inserting data
A
annie_wangli 已提交
32
  
A
Annie_wang 已提交
33

A
Annie_wang 已提交
34 35
  | Class      | API                                                      | Description                                                        |
  | ---------- | ------------------------------------------------------------ | ------------------------------------------------------------ |
A
Annie_wang 已提交
36
  | RdbStore | insert(table: string, values: ValuesBucket): Promise&lt;number&gt; | Inserts a row of data into a table. This API uses a promise to return the result.<br>If the operation is successful, the row ID will be returned; otherwise, **-1** will be returned.<br>- **table**: name of the target table.<br>- **values**: data to be inserted into the table.|
A
annie_wangli 已提交
37
  
A
Annie_wang 已提交
38
- **Updating Data**
A
annie_wangli 已提交
39
  
A
Annie_wang 已提交
40
  Call **update()** to pass the new data and specify the update conditions by using **RdbPredicates**. If the data is updated, the number of rows of the updated data will be returned; otherwise, **0** will be returned.
A
annie_wangli 已提交
41
  
A
Annie_wang 已提交
42
  **Table 3** API for updating data
A
annie_wangli 已提交
43
  
A
Annie_wang 已提交
44

A
Annie_wang 已提交
45
  | Class      | API                                                      | Description                                                        |
A
Annie_wang 已提交
46
  | ---------- | ------------------------------------------------------------ | ------------------------------------------------------------ |
A
Annie_wang 已提交
47
  | RdbStore | update(values: ValuesBucket, predicates: RdbPredicates): Promise&lt;number&gt; | Updates data based on the specified **RdbPredicates** object. This API uses a promise to return the number of rows updated.<br>- **values**: data to update, which is stored in **ValuesBucket**.<br>- **predicates**: conditions for updating data.|
A
annie_wangli 已提交
48
  
A
Annie_wang 已提交
49
- **Deleting Data**
A
annie_wangli 已提交
50
  
A
Annie_wang 已提交
51
  Call **delete()** to delete the data that meets the conditions specified by **RdbPredicates**. If the data is deleted, the number of rows of the deleted data will be returned; otherwise, **0** will be returned.
A
annie_wangli 已提交
52
  
A
Annie_wang 已提交
53
  **Table 4** API for deleting data
A
annie_wangli 已提交
54
  
A
Annie_wang 已提交
55

A
Annie_wang 已提交
56
  | Class      | API                                                    | Description                                                        |
A
Annie_wang 已提交
57
  | ---------- | ---------------------------------------------------------- | ------------------------------------------------------------ |
A
Annie_wang 已提交
58
  | RdbStore | delete(predicates: RdbPredicates): Promise&lt;number&gt; | Deletes data from the RDB store based on the specified **RdbPredicates** object. This API uses a promise to return the number of rows deleted.<br>- **predicates**: conditions for deleting data.|
A
Annie_wang 已提交
59 60
  
- **Querying Data**
A
annie_wangli 已提交
61 62 63 64 65 66 67

  You can query data in an RDB store in either of the following ways:

  - Call the **query()** method to query data based on the predicates, without passing any SQL statement.
  - Run the native SQL statement.

  **Table 5** APIs for querying data
A
annie_wangli 已提交
68

A
Annie_wang 已提交
69 70 71 72 73
  | Class      | API                                                      | Description                                                        |
  | ---------- | ------------------------------------------------------------ | ------------------------------------------------------------ |
  | RdbStore | query(predicates: RdbPredicates, columns?: Array&lt;string&gt;): Promise&lt;ResultSet&gt; | Queries data from the RDB store based on specified conditions. This API uses a promise to return the result.<br>- **predicates**: conditions for querying data.<br>- **columns**: columns to query. If this parameter is not specified, the query applies to all columns.|
  | RdbStore | querySql(sql: string, bindArgs?: Array&lt;ValueType&gt;): Promise&lt;ResultSet&gt; | Queries data using the specified SQL statement. This API uses a promise to return the result.<br>- **sql**: SQL statement.<br>- **bindArgs**: arguments in the SQL statement.|
  | RdbStore | remoteQuery(device: string, table: string, predicates: RdbPredicates, columns: Array&lt;string&gt;): Promise&lt;ResultSet&gt; | Queries data from the database of a remote device based on specified conditions. This API uses a promise to return the result.<br>- **device**: network ID of the remote device.<br>- **table**: name of the table to be queried.<br>- **predicates**: **RdbPredicates** that specifies the query condition.<br>- **columns**: columns to query. If this parameter is not specified, the query applies to all columns.|
Z
zengyawen 已提交
74

A
annie_wangli 已提交
75
### Using Predicates
Z
zengyawen 已提交
76

A
Annie_wang 已提交
77
The **RDB** module provides **RdbPredicates** for you to set database operation conditions.
A
annie_wangli 已提交
78

A
Annie_wang 已提交
79
The following table lists common predicates. For more information about predicates, see [**RdbPredicates**](../reference/apis/js-apis-data-relationalStore.md#rdbpredicates).
A
Annie_wang 已提交
80

A
annie_wangli 已提交
81 82
**Table 6** APIs for using RDB store predicates

A
Annie_wang 已提交
83
| Class           | API                                                      | Description                                                        |
A
Annie_wang 已提交
84
| --------------- | ------------------------------------------------------------ | ------------------------------------------------------------ |
A
Annie_wang 已提交
85 86 87 88 89
| RdbPredicates | equalTo(field: string, value: ValueType): RdbPredicates    | Sets an **RdbPredicates** to search for the data that is equal to the specified value.<br>- **field**: column name in the database table.<br>- **value**: value to match the **RdbPredicates**.<br>- **RdbPredicates**: **RdbPredicates** object created.|
| RdbPredicates | notEqualTo(field: string, value: ValueType): RdbPredicates | Sets an **RdbPredicates** to search for the data that is not equal to the specified value.<br>- **field**: column name in the database table.<br>- **value**: value to match the **RdbPredicates**.<br>- **RdbPredicates**: **RdbPredicates** object created.|
| RdbPredicates | or(): RdbPredicates                                        | Adds the OR condition to the **RdbPredicates**.<br>- **RdbPredicates**: **RdbPredicates** with the OR condition.|
| RdbPredicates | and(): RdbPredicates                                       | Adds the AND condition to the **RdbPredicates**.<br>- **RdbPredicates**: **RdbPredicates** with the AND condition.|
| RdbPredicates | contains(field: string, value: string): RdbPredicates      | Sets an **RdbPredicates** to search for the data that contains the specified value.<br>- **field**: column name in the database table.<br>- **value**: value to match the **RdbPredicates**.<br>- **RdbPredicates**: **RdbPredicates** object created.|
A
Annie_wang 已提交
90

Z
zengyawen 已提交
91

A
annie_wangli 已提交
92
### Using the Result Set
Z
zengyawen 已提交
93

A
Annie_wang 已提交
94
You can use the APIs provided by **ResultSet** to traverse and access the data you have queried. A result set can be regarded as a row of data in the queried result.
A
Annie_wang 已提交
95

A
Annie_wang 已提交
96
For details about how to use **ResultSet** APIs, see [ResultSet](../reference/apis/js-apis-data-relationalStore.md#resultset).
A
annie_wangli 已提交
97

A
Annie_wang 已提交
98
> **NOTICE**<br>
A
Annie_wang 已提交
99
> After a result set is used, you must call the **close()** method to close it explicitly.
A
annie_wangli 已提交
100 101 102

**Table 7** APIs for using the result set

A
Annie_wang 已提交
103 104
| Class       | API                                  | Description                                      |
| ----------- | ---------------------------------------- | ------------------------------------------ |
A
Annie_wang 已提交
105 106 107 108 109 110
| ResultSet | goToFirstRow(): boolean                  | Moves to the first row of the result set.                    |
| ResultSet | getString(columnIndex: number): string   | Obtains the value in the form of a string based on the specified column and current row.  |
| ResultSet | getBlob(columnIndex: number): Uint8Array | Obtains the value in the form of a byte array based on the specified column and the current row.|
| ResultSet | getDouble(columnIndex: number): number   | Obtains the value in the form of double based on the specified column and current row.    |
| ResultSet | getLong(columnIndex: number): number     | Obtains the value in the form of a long integer based on the specified column and current row.    |
| ResultSet | close(): void                            | Closes the result set.                              |
A
annie_wangli 已提交
111

Z
zengyawen 已提交
112 113


A
annie_wangli 已提交
114
### Setting Distributed Tables
A
annie_wangli 已提交
115

A
Annie_wang 已提交
116 117
> **NOTE** 
>
A
Annie_wang 已提交
118
> - The **ohos.permission.DISTRIBUTED_DATASYNC** permission is required for calling the **setDistributedTables**, **obtainDistributedTableName**, **sync**, **on** and **off** APIs of **RdbStore**.
A
Annie_wang 已提交
119
> - The devices must be connected over network before the distributed tables are used. For details about the APIs and usage, see [Device Management](../reference/apis/js-apis-device-manager.md).
A
Annie_wang 已提交
120

A
annie_wangli 已提交
121 122
**Setting Distributed Tables**

A
Annie_wang 已提交
123
**Table 8** API for setting distributed tables
A
annie_wangli 已提交
124

A
Annie_wang 已提交
125 126
| Class      | API                                                      | Description                                                        |
| ---------- | ------------------------------------------------------------ | ------------------------------------------------------------ |
A
Annie_wang 已提交
127
| RdbStore | setDistributedTables(tables: Array\<string>): Promise\<void> | Sets distributed tables. This API uses a promise to return the result.<br>- **tables**: names of the distributed tables to set.|
A
annie_wangli 已提交
128 129 130 131 132

**Obtaining the Distributed Table Name for a Remote Device**

You can obtain the distributed table name for a remote device based on the local table name. The distributed table name can be used to query the RDB store of the remote device.

A
Annie_wang 已提交
133
**Table 9** API for obtaining the distributed table name of a remote device
A
annie_wangli 已提交
134

A
Annie_wang 已提交
135 136
| Class      | API                                                      | Description                                                        |
| ---------- | ------------------------------------------------------------ | ------------------------------------------------------------ |
A
Annie_wang 已提交
137
| RdbStore | obtainDistributedTableName(device: string, table: string): Promise\<string> | Obtains the distributed table name for a remote device based on the local table name. The distributed table name is required when the RDB store of a remote device is queried. This API uses a promise to return the result.<br>- **device**: remote device.<br>- **table**: local table name.|
A
annie_wangli 已提交
138 139 140

**Synchronizing Data Between Devices**

A
Annie_wang 已提交
141
**Table 10** API for synchronizing data between devices
A
annie_wangli 已提交
142

A
Annie_wang 已提交
143 144
| Class      | API                                                      | Description                                                        |
| ---------- | ------------------------------------------------------------ | ------------------------------------------------------------ |
A
Annie_wang 已提交
145
| RdbStore | sync(mode: SyncMode, predicates: RdbPredicates): Promise\<Array\<[string, number]>> | Synchronizes data between devices. This API uses a promise to return the result.<br>- **mode**: synchronization mode. **SYNC_MODE_PUSH** means to push data from the local device to a remote device. **SYNC_MODE_PULL** means to pull data from a remote device to the local device.<br>- **predicates**: specifies the data and devices to synchronize.<br>- **string**: device ID. <br>- **number**: synchronization status of each device. The value **0** indicates a successful synchronization. Other values indicate a synchronization failure.|
A
annie_wangli 已提交
146 147

**Registering an RDB Store Observer**
Z
zengyawen 已提交
148

A
annie_wangli 已提交
149
**Table 11** API for registering an observer
Z
zengyawen 已提交
150

A
Annie_wang 已提交
151 152
| Class      | API                                                      | Description                                                        |
| ---------- | ------------------------------------------------------------ | ------------------------------------------------------------ |
A
Annie_wang 已提交
153
| RdbStore | on(event: 'dataChange', type: SubscribeType, observer: Callback\<Array\<string>>): void | Registers an observer for this RDB store to subscribe to distributed data changes. When data in the RDB store changes, a callback will be invoked to return the data changes.<br>- **type**: subscription type. **SUBSCRIBE_TYPE_REMOTE**: subscribes to remote data changes.<br>- **observer**: observer that listens for data changes in the RDB store.|
A
annie_wangli 已提交
154 155 156

**Unregistering an RDB Store Observer**

A
annie_wangli 已提交
157
**Table 12** API for unregistering an observer
A
annie_wangli 已提交
158

A
Annie_wang 已提交
159 160
| Class      | API                                                      | Description                                                        |
| ---------- | ------------------------------------------------------------ | ------------------------------------------------------------ |
A
Annie_wang 已提交
161
| RdbStore | off(event:'dataChange', type: SubscribeType, observer: Callback\<Array\<string>>): void; | Unregisters the observer of the specified type from the RDB store. This API uses an asynchronous callback to return the result.<br>- **type**: subscription type. **SUBSCRIBE_TYPE_REMOTE**: subscribes to remote data changes.<br>- **observer**: observer to unregister.|
A
Annie_wang 已提交
162

A
Annie_wang 已提交
163
### Backing Up and Restoring an RDB Store
A
Annie_wang 已提交
164 165 166

**Backing Up an RDB Store**

A
Annie_wang 已提交
167
**Table 13** API for backing up an RDB store
A
Annie_wang 已提交
168

A
Annie_wang 已提交
169 170
| Class      | API                                       | Description                                                        |
| ---------- | --------------------------------------------- | ------------------------------------------------------------ |
A
Annie_wang 已提交
171
| RdbStore | backup(destName: string): Promise&lt;void&gt; | Backs up an RDB store. This API uses a promise to return the result.<br>- **destName**: name of the RDB backup file.|
A
annie_wangli 已提交
172

A
Annie_wang 已提交
173 174
**Restoring an RDB Store**

A
Annie_wang 已提交
175
**Table 14** API for restoring an RDB store
A
Annie_wang 已提交
176

A
Annie_wang 已提交
177 178
| Class      | API                                       | Description                                                        |
| ---------- | --------------------------------------------- | ------------------------------------------------------------ |
A
Annie_wang 已提交
179
| RdbStore | restore(srcName: string): Promise&lt;void&gt; | Restores an RDB store from a backup file. This API uses a promise to return the result.<br>- **srcName**: name of the backup file used to restore the RDB store.|
A
annie_wangli 已提交
180

A
Annie_wang 已提交
181
### Transaction
A
Annie_wang 已提交
182

A
Annie_wang 已提交
183
**Table 15** Transaction APIs
A
Annie_wang 已提交
184

A
Annie_wang 已提交
185 186
| Class    | API                 | Description                             |
| -------- | ----------------------- | --------------------------------- |
A
Annie_wang 已提交
187 188 189
| RdbStore | beginTransaction(): void | Starts the transaction before executing SQL statements.|
| RdbStore | commit(): void           | Commits the executed SQL statements.            |
| RdbStore | rollBack(): void         | Rolls back the SQL statements that have been executed.          |
A
Annie_wang 已提交
190

A
annie_wangli 已提交
191 192 193
## How to Develop

1. Create an RDB store.
A
Annie_wang 已提交
194 195 196 197 198 199

   (1) Configure the RDB store attributes, including the RDB store name, storage mode, and whether read-only mode is used.

   (2) Initialize the table structure and related data in the RDB store.

   (3) Create an RDB store.
A
annie_wangli 已提交
200

A
Annie_wang 已提交
201
   FA model:
A
annie_wangli 已提交
202

A
Annie_wang 已提交
203
    ```js
A
Annie_wang 已提交
204
   import relationalStore from '@ohos.data.relationalStore'
A
Annie_wang 已提交
205
   import featureAbility from '@ohos.ability.featureAbility'
A
Annie_wang 已提交
206
   
A
Annie_wang 已提交
207 208
   var store;
   
A
Annie_wang 已提交
209
   // Obtain the context.
A
Annie_wang 已提交
210
   let context = featureAbility.getContext();
A
Annie_wang 已提交
211
   
A
Annie_wang 已提交
212 213
   const STORE_CONFIG = { 
       name: "RdbTest.db",
A
Annie_wang 已提交
214 215
       securityLevel: relationalStore.SecurityLevel.S1
   };
A
Annie_wang 已提交
216
   
A
Annie_wang 已提交
217
   // Assume that the current RDB store version is 3.
A
Annie_wang 已提交
218 219 220 221 222 223 224 225
   relationalStore.getRdbStore(context, STORE_CONFIG, function (err, rdbStore) {
     store = rdbStore;
     // When an RDB store is created, the default version is 0.
     if (store.version == 0) {
       store.executeSql("CREATE TABLE IF NOT EXISTS student (id INTEGER PRIMARY KEY AUTOINCREMENT, score REAL);", null);
       // Set the RDB store version. The input parameter must be an integer greater than 0.
       store.version = 3;
     }
A
Annie_wang 已提交
226
        
A
Annie_wang 已提交
227 228 229 230 231 232
     // When an app is updated to the current version, the RDB store needs to be updated from version 1 to version 2.
     if (store.version != 3 && store.version == 1) {
       // version = 1: table structure: student (id, age) => version = 2: table structure: student (id, age, score)
       store.executeSql("ALTER TABLE student ADD COLUMN score REAL", null);
       store.version = 2;
     }
A
Annie_wang 已提交
233
        
A
Annie_wang 已提交
234 235 236 237 238 239
     // When an app is updated to the current version, the RDB store needs to be updated from version 2 to version 3.
     if (store.version != 3 && store.version == 2) {
       // version = 2: table structure: student (id, age, score) => version = 3: table structure: student (id, score)
       store.executeSql("ALTER TABLE student DROP COLUMN age INTEGER", null);
       store.version = 3;
     }
A
Annie_wang 已提交
240 241 242 243
   })
    ```
    Stage model:
     ```ts
A
Annie_wang 已提交
244
   import relationalStore from '@ohos.data.relationalStore'
A
Annie_wang 已提交
245 246
   import UIAbility from '@ohos.app.ability.UIAbility'
   
A
Annie_wang 已提交
247
   class EntryAbility extends UIAbility {
A
Annie_wang 已提交
248
       onWindowStageCreate(windowStage) {
A
Annie_wang 已提交
249 250 251 252 253
         var store;   
         const STORE_CONFIG = {
           name: "RdbTest.db",
           securityLevel: relationalStore.SecurityLevel.S1
         };
A
Annie_wang 已提交
254
   
A
Annie_wang 已提交
255 256 257 258 259 260 261 262 263
         // Assume that the current RDB store version is 3.
         relationalStore.getRdbStore(this.context, STORE_CONFIG, function (err, rdbStore) {
           store = rdbStore;
           // When an RDB store is created, the default version is 0.
           if (store.version == 0) {
             store.executeSql("CREATE TABLE IF NOT EXISTS student (id INTEGER PRIMARY KEY AUTOINCREMENT, score REAL);", null);
             // Set the RDB store version. The input parameter must be an integer greater than 0.
             store.version = 3;
           }
A
Annie_wang 已提交
264
    
A
Annie_wang 已提交
265 266 267 268 269 270
           // When an app is updated to the current version, the RDB store needs to be updated from version 1 to version 2.
           if (store.version != 3 && store.version == 1) {
             // version = 1: table structure: student (id, age) => version = 2: table structure: student (id, age, score)
             store.executeSql("ALTER TABLE student ADD COLUMN score REAL", null);
             store.version = 2;
           }
A
Annie_wang 已提交
271
    
A
Annie_wang 已提交
272 273 274 275 276 277 278
           // When an app is updated to the current version, the RDB store needs to be updated from version 2 to version 3.
           if (store.version != 3 && store.version == 2) {
             // version = 2: table structure: student (id, age, score) => version = 3: table structure: student (id, score)
             store.executeSql("ALTER TABLE student DROP COLUMN age INTEGER", null);
             store.version = 3;
           }
         })
A
Annie_wang 已提交
279 280
       }
   }
A
Annie_wang 已提交
281
     ```
A
annie_wangli 已提交
282 283

2. Insert data.
A
Annie_wang 已提交
284

A
Annie_wang 已提交
285
   (1) Create a **ValuesBucket** instance to store the data you need to insert.
A
Annie_wang 已提交
286 287

   (2) Call the **insert()** method to insert data into the RDB store.
A
annie_wangli 已提交
288 289 290

   The sample code is as follows:

A
Annie_wang 已提交
291
    ```js
A
Annie_wang 已提交
292 293 294
    let u8 = new Uint8Array([1, 2, 3]);
    const valueBucket = { "name": "Tom", "age": 18, "salary": 100.5, "blobType": u8 };
    let insertPromise = store.insert("test", valueBucket);
A
Annie_wang 已提交
295 296 297 298 299
    ```
   
    ```js
    // Use a transaction to insert data.
    try {
A
Annie_wang 已提交
300 301 302 303 304 305 306 307 308 309
      store.beginTransaction();
      let u8 = new Uint8Array([1, 2, 3]);
      const valueBucket = { "name": "Tom", "age": 18, "salary": 100.5, "blobType": u8 };
      let promise = store.insert("test", valueBucket);
      promise.then(() => {
        store.commit();
      })
    } catch (err) {
      console.error(`Transaction failed, err: ${err}`);
      store.rollBack();
A
Annie_wang 已提交
310
    }
A
Annie_wang 已提交
311
    ```
A
annie_wangli 已提交
312 313

3. Query data.
A
Annie_wang 已提交
314

A
Annie_wang 已提交
315
   (1) Create an **RdbPredicates** object to specify query conditions.
A
Annie_wang 已提交
316

A
Annie_wang 已提交
317
   (2) Call the **query()** API to query data.
A
Annie_wang 已提交
318

A
Annie_wang 已提交
319
   (3) Call the **resultSet()** API to obtain the result.
A
annie_wangli 已提交
320 321 322

   The sample code is as follows:

A
Annie_wang 已提交
323
    ```js
A
Annie_wang 已提交
324 325 326
    let predicates = new relationalStore.RdbPredicates("test");
    predicates.equalTo("name", "Tom");
    let promisequery = store.query(predicates);
A
Annie_wang 已提交
327
    promisequery.then((resultSet) => {
A
Annie_wang 已提交
328 329 330 331 332 333 334
      resultSet.goToFirstRow();
      const id = resultSet.getLong(resultSet.getColumnIndex("id"));
      const name = resultSet.getString(resultSet.getColumnIndex("name"));
      const age = resultSet.getLong(resultSet.getColumnIndex("age"));
      const salary = resultSet.getDouble(resultSet.getColumnIndex("salary"));
      const blobType = resultSet.getBlob(resultSet.getColumnIndex("blobType"));
      resultSet.close();
A
Annie_wang 已提交
335
    })
A
Annie_wang 已提交
336
    ```
A
annie_wangli 已提交
337 338

4. Set the distributed tables to be synchronized.
A
Annie_wang 已提交
339 340 341

    (1) Add the following permission to the permission configuration file:   

342
    ```json
A
Annie_wang 已提交
343
    "requestPermissions": 
A
Annie_wang 已提交
344 345 346
    {
      "name": "ohos.permission.DISTRIBUTED_DATASYNC"
    }
A
Annie_wang 已提交
347
    ```
A
Annie_wang 已提交
348

A
Annie_wang 已提交
349
    (2) Obtain the required permissions.
A
Annie_wang 已提交
350 351 352 353

    (3) Set the distributed tables.

    (4) Check whether the setting is successful.
A
annie_wangli 已提交
354 355 356

   The sample code is as follows:

A
Annie_wang 已提交
357 358 359
    ```js
    let context = featureAbility.getContext();
    context.requestPermissionsFromUser(['ohos.permission.DISTRIBUTED_DATASYNC'], 666, function (result) {
A
Annie_wang 已提交
360
      console.info(`result.requestCode=${result.requestCode}`);
A
Annie_wang 已提交
361
    })
A
Annie_wang 已提交
362
    let promise = store.setDistributedTables(["test"]);
A
Annie_wang 已提交
363
    promise.then(() => {
A
Annie_wang 已提交
364
      console.info(`setDistributedTables success.`);
A
Annie_wang 已提交
365
    }).catch((err) => {
A
Annie_wang 已提交
366
      console.error(`setDistributedTables failed, ${err}`);
A
Annie_wang 已提交
367 368
    })
    ```
A
annie_wangli 已提交
369

A
Annie_wang 已提交
370
5. Synchronize data across devices.
A
Annie_wang 已提交
371

A
Annie_wang 已提交
372
    (1) Construct an **RdbPredicates** object to specify remote devices within the network to be synchronized.
A
Annie_wang 已提交
373 374 375 376

    (2) Call **rdbStore.sync()** to synchronize data.

    (3) Check whether the data synchronization is successful.
Z
zengyawen 已提交
377 378 379

    The sample code is as follows:

380
    ```js
A
Annie_wang 已提交
381 382 383
    let predicate = new relationalStore.RdbPredicates('test');
    predicate.inDevices(['12345678abcde']);
    let promise = store.sync(relationalStore.SyncMode.SYNC_MODE_PUSH, predicate);
A
annie_wangli 已提交
384
    promise.then((result) => {
A
Annie_wang 已提交
385 386 387 388
      console.info(`sync done.`);
      for (let i = 0; i < result.length; i++) {
        console.info(`device=${result[i][0]}, status=${result[i][1]}`);
      }
A
annie_wangli 已提交
389
    }).catch((err) => {
A
Annie_wang 已提交
390
      console.error(`sync failed, err: ${err}`);
A
annie_wangli 已提交
391
    })
Z
zengyawen 已提交
392 393
    ```

A
annie_wangli 已提交
394
6. Subscribe to distributed data.
A
Annie_wang 已提交
395 396 397 398
  
    (1) Register an observer to listen for distributed data changes.

    (2) When data in the RDB store changes, a callback will be invoked to return the data changes.
Z
zengyawen 已提交
399 400 401

    The sample code is as follows:

402
    ```js
A
annie_wangli 已提交
403
    function storeObserver(devices) {
A
Annie_wang 已提交
404 405 406
      for (let i = 0; i < devices.length; i++) {
        console.info(`device= ${devices[i]} data changed`);
      }
A
annie_wangli 已提交
407
    }
A
Annie_wang 已提交
408
    
A
annie_wangli 已提交
409
    try {
A
Annie_wang 已提交
410
      store.on('dataChange', relationalStore.SubscribeType.SUBSCRIBE_TYPE_REMOTE, storeObserver);
A
annie_wangli 已提交
411
    } catch (err) {
A
Annie_wang 已提交
412
      console.error(`register observer failed, err: ${err}`);
A
annie_wangli 已提交
413
    }
Z
zengyawen 已提交
414 415
    ```

A
annie_wangli 已提交
416
7. Query data across devices.
A
Annie_wang 已提交
417 418 419 420
   
    (1) Obtain the distributed table name for a remote device based on the local table name.

    (2) Call the resultSet() API to obtain the result.
A
annie_wangli 已提交
421 422

    The sample code is as follows:
Z
zengyawen 已提交
423

424
    ```js
A
Annie_wang 已提交
425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442
   import deviceManager from '@ohos.distributedHardware.deviceManager'
  
   let deviceIds = [];
   deviceManager.createDeviceManager('bundleName', (err, value) => {
     if (!err) {
       let devManager = value;
       if (devManager != null) {
         // Obtain device IDs.
         let devices = devManager.getTrustedDeviceListSync();
         for (let i = 0; i < devices.length; i++) {
           deviceIds[i] = devices[i].deviceId;
         }
       }
     }
   })
   
   let tableName = store.obtainDistributedTableName(deviceIds[0], "test");
   let resultSet = store.querySql("SELECT * FROM " + tableName);
A
annie_wangli 已提交
443
    ```
A
Annie_wang 已提交
444 445 446 447 448 449 450 451
    
8. Query data of a remote device.
   
   (1) Construct a predicate object for querying distributed tables, and specify the remote distributed table name and the remote device.
   
   (2) Call the resultSet() API to obtain the result.
   
   The sample code is as follows:
A
Annie_wang 已提交
452 453

   ```js
A
Annie_wang 已提交
454 455 456
    let rdbPredicate = new relationalStore.RdbPredicates('employee');
    predicates.greaterThan("id", 0) ;
    let promiseQuery = store.remoteQuery('12345678abcde', 'employee', rdbPredicate);
A
Annie_wang 已提交
457
    promiseQuery.then((resultSet) => {
A
Annie_wang 已提交
458 459 460 461 462 463 464
      while (resultSet.goToNextRow()) {
        let idx = resultSet.getLong(0);
        let name = resultSet.getString(1);
        let age = resultSet.getLong(2);
        console.info(`indx: ${idx}, name: ${name}, age: ${age}`);
      }
      resultSet.close();
A
Annie_wang 已提交
465
    }).catch((err) => {
A
Annie_wang 已提交
466
      console.error(`failed to remoteQuery, err: ${err}`);
A
Annie_wang 已提交
467
    })
A
Annie_wang 已提交
468 469
   ```

A
Annie_wang 已提交
470
9. Back up and restore an RDB store.
A
Annie_wang 已提交
471 472 473

   (1) Back up the current RDB store.

A
Annie_wang 已提交
474
   The sample code is as follows:
A
Annie_wang 已提交
475

A
Annie_wang 已提交
476
   ```js
A
Annie_wang 已提交
477
    let promiseBackup = store.backup("dbBackup.db");
A
Annie_wang 已提交
478
    promiseBackup.then(() => {
A
Annie_wang 已提交
479
      console.info(`Backup success.`);
A
Annie_wang 已提交
480
    }).catch((err) => {
A
Annie_wang 已提交
481
      console.error(`Backup failed, err: ${err}`);
A
Annie_wang 已提交
482
    })
A
Annie_wang 已提交
483
   ```
A
Annie_wang 已提交
484
   
A
Annie_wang 已提交
485
   (2) Restore the RDB store using the backup file.
A
Annie_wang 已提交
486

A
Annie_wang 已提交
487 488 489
   The sample code is as follows:

   ```js
A
Annie_wang 已提交
490
    let promiseRestore = store.restore("dbBackup.db");
A
Annie_wang 已提交
491
    promiseRestore.then(() => {
A
Annie_wang 已提交
492
      console.info(`Restore success.`);
A
Annie_wang 已提交
493
    }).catch((err) => {
A
Annie_wang 已提交
494
      console.error(`Restore failed, err: ${err}`);
A
Annie_wang 已提交
495
    })
A
Annie_wang 已提交
496
   ```