All Products
Search
Document Center

Tablestore:Write data

Last Updated:Jan 05, 2024

Tablestore allows you to write a single row of data, update a single row of data, and write multiple rows of data at a time by calling different operations. To write data to a data table, you must specify the complete primary key information and the attribute columns that you want to add, delete, or modify. To write data to a highly concurrent application, you can configure row existence conditions or column conditions to update data based on the specified conditions.

Note

In the examples in this topic, pkValue represents the primary key column value. Replace pkValue with the actual primary key column value when you call the operations.

Write methods

Tablestore provides the PutRow, UpdateRow, and BatchWriteRow operations to allow you to write data. Before you write data, select a suitable write method based on your business requirements.

Write method

Description

Scenario

Write a single row of data

You can call the PutRow operation to write a row of data. If the row exists, Tablestore deletes all versions of data in all columns from the existing row and writes new data.

This method is applicable to scenarios in which you want to write a small amount of data.

Update a single row of data

You can call the UpdateRow operation to update the data in a row. You can add attribute columns to a row, remove attribute columns from a row, delete a specific version of data from an attribute column, or update the value of an attribute column. If the row does not exist, a new row is inserted.

This method is applicable to scenarios in which you want to update the existing data, such as removing an attribute column, deleting a specific version of data, or updating the value of an attribute column.

Write multiple rows of data at a time

You can call the BatchWriteRow operation to write multiple rows of data to one or more tables at a time.

The BatchWriteRow operation consists of multiple PutRow, UpdateRow, and DeleteRow operations. When you call the BatchWriteRow operation, the process of constructing a suboperation is the same as the process of calling the PutRow, UpdateRow, or DeleteRow operation.

This method is applicable to scenarios in which you want to write, delete, or update a large amount of data and scenarios in which you want to write, delete, and update data at the same time.

Prerequisites

  • An OTSClient instance is initialized. For more information, see Initialize a client.

  • A data table is created, and data is written to the data table.

Write a single row of data

You can call the PutRow operation to write a row of data. If the row exists, Tablestore deletes all versions of data in all columns from the existing row and writes new data.

Parameters

Parameter

Description

tableName

The name of the data table.

primaryKey

The primary key information of the row. The value of this parameter contains the name of each primary key column, the type of the primary key column, and the primary key value.

Important
  • The number and types of primary key columns that you specify must be the same as the actual number and types of primary key columns in the table.

  • If a primary key column is an auto-increment primary key column, you need to only set the value of the auto-increment primary key column to a placeholder. For more information, see Configure an auto-increment primary key column.

condition

The conditions that must be met for the operation to be performed. You can specify a row existence condition or a condition based on column values. For more information, see Configure conditional update.

Note
  • RowExistenceExpectation.IGNORE specifies that new data is inserted into a row regardless of whether the specified row exists. If the specified row exists, the existing data is overwritten.

  • RowExistenceExpectation.EXPECT_EXIST specifies that new data is inserted only when the specified row exists. The existing data is overwritten.

  • RowExistenceExpectation.EXPECT_NOT_EXIST specifies that new data is inserted only when the specified row does not exist.

column

The attribute columns of the row. Each attribute column is specified by the following items in sequence: the attribute column name, attribute column value type, attribute column value, and timestamp. The attribute column value type and timestamp are optional.

  • The attribute column name is the name of the attribute column, and the attribute column value type is the data type of the attribute column. For more information, see Naming conventions and data types.

    You can set the attribute column value type to ColumnType.INTEGER, ColumnType.STRING, ColumnType.BINARY, ColumnType.BOOLEAN, or ColumnType.DOUBLE. A value of ColumnType.STRING specifies UTF-8 encoded STRING. To insert BINARY data, you must set the attribute column value type to ColumnType.BINARY. To insert data of the other types, you do not need to specify an attribute column value type.

  • A timestamp is a data version number. You can use the data version number that is automatically generated by the system or specify a custom data version number. By default, if you do not specify a data version number, the data version number that is automatically generated by the system is used. For more information, see Data versions and TTL.

    • By default, the system uses the current UNIX timestamp as a data version number. A UNIX timestamp represents the number of milliseconds that have elapsed since January 1, 1970, 00:00:00 UTC.

    • If you specify a custom data version number, make sure that the version number is a 64-bit timestamp that is accurate to milliseconds and is in the valid version range.

Examples

Use the data version number that is automatically generated by the system when you write a row of data

The following sample code provides an example on how to write a row that contains 10 attribute columns, each of which stores data of only one version. In this example, data version numbers are automatically generated by the system.

private static void putRow(SyncClient client, String pkValue) {
    // Construct the primary key. 
    PrimaryKeyBuilder primaryKeyBuilder = PrimaryKeyBuilder.createPrimaryKeyBuilder();
    primaryKeyBuilder.addPrimaryKeyColumn("pk", PrimaryKeyValue.fromString(pkValue));
    PrimaryKey primaryKey = primaryKeyBuilder.build();
    // Specify the name of the table. 
    RowPutChange rowPutChange = new RowPutChange("<TABLE_NAME>", primaryKey);

    // Add attribute columns. 
    for (int i = 0; i < 10; i++) {
        rowPutChange.addColumn(new Column("Col" + i, ColumnValue.fromLong(i)));
    }

    client.putRow(new PutRowRequest(rowPutChange));
}
                    

Specify a custom data version number when you write a row of data

The following sample code provides an example on how to write a row that contains 10 attribute columns, each of which stores data of three versions. In this example, custom data version numbers are specified.

private static void putRow(SyncClient client, String pkValue) {
    // Construct the primary key. 
    PrimaryKeyBuilder primaryKeyBuilder = PrimaryKeyBuilder.createPrimaryKeyBuilder();
    primaryKeyBuilder.addPrimaryKeyColumn("pk", PrimaryKeyValue.fromString(pkValue));
    PrimaryKey primaryKey = primaryKeyBuilder.build();
    // Specify the name of the table. 
    RowPutChange rowPutChange = new RowPutChange("<TABLE_NAME>", primaryKey);

    // Add attribute columns. 
    long ts = System.currentTimeMillis();
    for (int i = 0; i < 10; i++) {
        for (int j = 0; j < 3; j++) {
            rowPutChange.addColumn(new Column("Col" + i, ColumnValue.fromLong(j), ts + j));
        }
    }

    client.putRow(new PutRowRequest(rowPutChange));
}
                    

Specify a row existence condition when you write a row of data

The following sample code provides an example on how to write a row that contains 10 attribute columns, each of which stores data of three versions, when the specified row does not exist. In this example, custom data version numbers are specified.

private static void putRow(SyncClient client, String pkValue) {
    // Construct the primary key. 
    PrimaryKeyBuilder primaryKeyBuilder = PrimaryKeyBuilder.createPrimaryKeyBuilder();
    primaryKeyBuilder.addPrimaryKeyColumn("pk", PrimaryKeyValue.fromString(pkValue));
    PrimaryKey primaryKey = primaryKeyBuilder.build();
    // Specify the name of the table. 
    RowPutChange rowPutChange = new RowPutChange("<TABLE_NAME>", primaryKey);

    // Specify a row existence condition that expects the specified row to not exist. 
    rowPutChange.setCondition(new Condition(RowExistenceExpectation.EXPECT_NOT_EXIST));

    // Add attribute columns. 
    long ts = System.currentTimeMillis();
    for (int i = 0; i < 10; i++) {
        for (int j = 0; j < 3; j++) {
            rowPutChange.addColumn(new Column("Col" + i, ColumnValue.fromLong(j), ts + j));
        }
    }

    client.putRow(new PutRowRequest(rowPutChange));
}                   

Specify a column-based condition and a row existence condition when you write a row of data

The following sample code provides an example on how to write a row that contains 10 attribute columns, each of which stores data of three versions, when the specified row exists and the value of the Col0 column is greater than 100. In this example, custom data version numbers are specified.

private static void putRow(SyncClient client, String pkValue) {
    // Construct the primary key. 
    PrimaryKeyBuilder primaryKeyBuilder = PrimaryKeyBuilder.createPrimaryKeyBuilder();
    primaryKeyBuilder.addPrimaryKeyColumn("pk", PrimaryKeyValue.fromString(pkValue));
    PrimaryKey primaryKey = primaryKeyBuilder.build();
    // Specify the name of the table. 
    RowPutChange rowPutChange = new RowPutChange("<TABLE_NAME>", primaryKey);

    // Specify a row existence condition and a column-based condition that expect the specified row to exist and the value of the Col0 column to be greater than 100. 
    Condition condition = new Condition(RowExistenceExpectation.EXPECT_EXIST);
    condition.setColumnCondition(new SingleColumnValueCondition("Col0",
            SingleColumnValueCondition.CompareOperator.GREATER_THAN, ColumnValue.fromLong(100)));
    rowPutChange.setCondition(condition);

    // Add attribute columns. 
    long ts = System.currentTimeMillis();
    for (int i = 0; i < 10; i++) {
        for (int j = 0; j < 3; j++) {
            rowPutChange.addColumn(new Column("Col" + i, ColumnValue.fromLong(j), ts + j));
        }
    }

    client.putRow(new PutRowRequest(rowPutChange));
}
                    

Update a single row of data

You can call the UpdateRow operation to update the data in a row. You can add attribute columns to a row, remove attribute columns from a row, delete a specific version of data from an attribute column, or update the value of an attribute column. If the row does not exist, a new row is inserted.

Note

If you call the UpdateRow operation only to remove columns from a row and the row does not exist, no row is inserted into the table.

Parameters

Parameter

Description

tableName

The name of the data table.

primaryKey

The primary key information of the row. The primary key information consists of the primary key column name, primary key type, and primary key value.

Important

The number and types of primary key columns that you specify must be the same as the actual number and types of primary key columns in the data table.

condition

The conditions that must be met for the operation to be performed. You can specify a row existence condition or a condition based on column values. For more information, see Configure conditional update.

column

The attribute columns you want to update.

  • When you add or modify an attribute column, you must specify the attribute column name and attribute column value. The attribute column value type and timestamp are optional.

    The attribute column name is the name of the attribute column, and the attribute column value type is the data type of the attribute column. For more information, see Naming conventions and data types.

    A timestamp is a data version number. You can use the data version number that is automatically generated by the system or specify a custom data version number. By default, if you do not specify a data version number, the data version number that is automatically generated by the system is used. For more information, see Data versions and TTL.

    • By default, the system uses the current UNIX timestamp as a data version number. A UNIX timestamp represents the number of milliseconds that have elapsed since January 1, 1970, 00:00:00 UTC.

    • If you specify a custom data version number, make sure that the version number is a 64-bit timestamp that is accurate to milliseconds and is in the valid version range.

  • To delete a specified version of data from an attribute column, you need to only specify the attribute column name and timestamp.

    The timestamp is a 64-bit integer in units of milliseconds, which specifies a version of data.

  • To remove an attribute column, you need to only specify the attribute column name.

    Note

    After you remove all attribute columns from a row, the row still exists. To delete a row, use the DeleteRow operation.

Examples

Update a row of data without specifying conditions

The following sample code provides an example on how to update multiple columns of a row, delete a specific version of data from a column, and remove a column:

private static void updateRow(SyncClient client, String pkValue) {
    // Construct the primary key. 
    PrimaryKeyBuilder primaryKeyBuilder = PrimaryKeyBuilder.createPrimaryKeyBuilder();
    primaryKeyBuilder.addPrimaryKeyColumn(PRIMARY_KEY_NAME, PrimaryKeyValue.fromString(pkValue));
    PrimaryKey primaryKey = primaryKeyBuilder.build();
    // Specify the name of the table. 
    RowUpdateChange rowUpdateChange = new RowUpdateChange("<TABLE_NAME>", primaryKey);

    // Update columns. 
    for (int i = 0; i < 10; i++) {
        rowUpdateChange.put(new Column("Col" + i, ColumnValue.fromLong(i)));
    }

    // Delete a specific version of data from a column. 
    rowUpdateChange.deleteColumn("Col10", 1465373223000L);

    // Remove a column. 
    rowUpdateChange.deleteColumns("Col11");

    client.updateRow(new UpdateRowRequest(rowUpdateChange));
}                   

Specify a column-based condition and a row existence condition when you update a row of data

The following sample code provides an example on how to update a row of data when the specified row exists and the value of the Col0 column is greater than 100:

private static void updateRow(SyncClient client, String pkValue) {
    // Construct the primary key. 
    PrimaryKeyBuilder primaryKeyBuilder = PrimaryKeyBuilder.createPrimaryKeyBuilder();
    primaryKeyBuilder.addPrimaryKeyColumn(PRIMARY_KEY_NAME, PrimaryKeyValue.fromString(pkValue));
    PrimaryKey primaryKey = primaryKeyBuilder.build();
    // Specify the name of the table. 
    RowUpdateChange rowUpdateChange = new RowUpdateChange("<TABLE_NAME>", primaryKey);

    // Specify a row existence condition and a column-based condition that expect the specified row to exist and the value of the Col0 column to be greater than 100. 
    Condition condition = new Condition(RowExistenceExpectation.EXPECT_EXIST);
    condition.setColumnCondition(new SingleColumnValueCondition("Col0",
            SingleColumnValueCondition.CompareOperator.GREATER_THAN, ColumnValue.fromLong(100)));
    rowUpdateChange.setCondition(condition);

    // Update columns. 
    for (int i = 0; i < 10; i++) {
        rowUpdateChange.put(new Column("Col" + i, ColumnValue.fromLong(i)));
    }

    // Delete a specific version of data from a column. 
    rowUpdateChange.deleteColumn("Col10", 1465373223000L);

    // Remove a column. 
    rowUpdateChange.deleteColumns("Col11");

    client.updateRow(new UpdateRowRequest(rowUpdateChange));
}         

Write multiple rows of data in a batch

You can call the BatchWriteRow operation to write multiple rows of data to one or more tables at a time.

The BatchWriteRow operation consists of multiple PutRow, UpdateRow, and DeleteRow operations. When you call the BatchWriteRow operation, the process of constructing a suboperation is the same as the process of calling the PutRow, UpdateRow, or DeleteRow operation.

When you call the BatchWriteRow operation, each PutRow, UpdateRow, or DeleteRow operation is separately performed and the response to each operation is separately returned by Tablestore.

Usage notes

  • When you call the BatchWriteRow operation to write multiple rows at a time, some rows may fail to be written. If this happens, Tablestore does not return exceptions, but returns BatchWriteRowResponse in which the information about the failed rows is included. Therefore, when you call the BatchWriteRow operation, you must check the return values. You can use the isAllSucceed method of BatchWriteRowResponse to check whether all rows are written. If you do not check the return values, you may ignore the rows that fail to be written.

  • If the server detects that invalid parameters exist in some operations, an error message may return before the operations of the request are performed.

Sample code

The following sample code provides an example on how to send a request for the BatchWriteRow operation, which consists of two PutRow operations, one DeleteRow operation, and one UpdateRow operation:

private static void batchWriteRow(SyncClient client) {
    BatchWriteRowRequest batchWriteRowRequest = new BatchWriteRowRequest();

    // Construct rowPutChange1. 
    PrimaryKeyBuilder pk1Builder = PrimaryKeyBuilder.createPrimaryKeyBuilder();
    pk1Builder.addPrimaryKeyColumn("pk", PrimaryKeyValue.fromString("pk1"));
    // Specify the name of the data table. 
    RowPutChange rowPutChange1 = new RowPutChange("<TABLE_NAME>", pk1Builder.build());
    // Add columns. 
    for (int i = 0; i < 10; i++) {
        rowPutChange1.addColumn(new Column("Col" + i, ColumnValue.fromLong(i)));
    }
    // Add rowPutChange1 to the code of the batch operation. 
    batchWriteRowRequest.addRowChange(rowPutChange1);

    // Construct rowPutChange2. 
    PrimaryKeyBuilder pk2Builder = PrimaryKeyBuilder.createPrimaryKeyBuilder();
    pk2Builder.addPrimaryKeyColumn("pk", PrimaryKeyValue.fromString("pk2"));
    // Specify the name of the data table. 
    RowPutChange rowPutChange2 = new RowPutChange("<TABLE_NAME>", pk2Builder.build());
    // Add columns. 
    for (int i = 0; i < 10; i++) {
        rowPutChange2.addColumn(new Column("Col" + i, ColumnValue.fromLong(i)));
    }
    // Add rowPutChange2 to the code of the batch operation. 
    batchWriteRowRequest.addRowChange(rowPutChange2);

    // Construct rowUpdateChange. 
    PrimaryKeyBuilder pk3Builder = PrimaryKeyBuilder.createPrimaryKeyBuilder();
    pk3Builder.addPrimaryKeyColumn("pk", PrimaryKeyValue.fromString("pk3"));
    // Specify the name of the data table. 
    RowUpdateChange rowUpdateChange = new RowUpdateChange("<TABLE_NAME>", pk3Builder.build());
    // Add columns. 
    for (int i = 0; i < 10; i++) {
        rowUpdateChange.put(new Column("Col" + i, ColumnValue.fromLong(i)));
    }
    // Remove a column. 
    rowUpdateChange.deleteColumns("Col10");
    // Add rowUpdateChange to the code of the batch operation. 
    batchWriteRowRequest.addRowChange(rowUpdateChange);

    // Construct rowDeleteChange. 
    PrimaryKeyBuilder pk4Builder = PrimaryKeyBuilder.createPrimaryKeyBuilder();
    pk4Builder.addPrimaryKeyColumn("pk", PrimaryKeyValue.fromString("pk4"));
    // Specify the name of the data table. 
    RowDeleteChange rowDeleteChange = new RowDeleteChange("<TABLE_NAME>", pk4Builder.build());
    // Add rowDeleteChange to the code of the batch operation. 
    batchWriteRowRequest.addRowChange(rowDeleteChange);

    BatchWriteRowResponse response = client.batchWriteRow(batchWriteRowRequest);

    System.out.println("Whether all operations are successful:" + response.isAllSucceed());
    if (!response.isAllSucceed()) {
        for (BatchWriteRowResponse.RowResult rowResult : response.getFailedRows()) {
            System.out.println("Failed rows:" + batchWriteRowRequest.getRowChange(rowResult.getTableName(), rowResult.getIndex()).getPrimaryKey());
            System.out.println("Cause of failures:" + rowResult.getError());
        }
        /**
         * You can use the createRequestForRetry method to construct another request to retry the operations on failed rows. Only the retry request is constructed here. 
         * We recommend that you use the custom retry policy in Tablestore SDKs as the retry method. This feature allows you to retry failed rows after batch operations. After you set the retry policy, you do not need to add retry code to call the operation. 
         */
        BatchWriteRowRequest retryRequest = batchWriteRowRequest.createRequestForRetry(response.getFailedRows());
    }
}            

To view the detailed sample code, visit BatchWriteRow@GitHub.

FAQ

References

  • To update data in a highly concurrent application based on the specified conditions, you can use the conditional update feature. For more information, see Perform conditional updates.

  • To collect real-time statistic data for online applications, such as the number of page views (PVs) on various topics, you can use the atomic counter feature. For more information, see Configure atomic counter.

  • To perform atomic operations to read or write one or more rows of data of a table, you can use the local transaction feature. For more information, see Use the local transaction feature.

  • After data is written to a table, you can read or delete the data of the table based on your business requirements. For more information, see Read data and Delete data.