Tablestore provides the PutRow and UpdateRow operations to allow you to write a single row of data, and the BatchWriteRow operation to allow you to write multiple rows of data in a batch.

Note Rows are basic units of tables. Rows consist of primary keys and attributes. A primary key is required for each row. Rows in a table contain primary key columns of the same names and same data types. Attributes are optional for each row. Rows in a table can also contain different attributes. For more information, see Overview.

Use Tablestore SDKs

You can use the following Tablestore SDKs to write data:

Insert a single row of data

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

CU consumption

The number of read and write capacity units (CUs) that are consumed by a PutRow operation is calculated based on the following rules:
  • The number of consumed write CUs is rounded up from the calculation results of the following formula: Number of consumed write CUs = (Size of the data in all primary key columns of the row + Size of the data in the inserted attribute columns)/4 KB.
  • If the value of the condition field is not IGNORE, the PutRow operation consumes read CUs. The number of consumed read CUs is rounded up from the calculation results of the following formula: Number of consumed read CUs = Size of the data in all primary key columns of the row/4 KB.
  • If row existence conditions are not met, the operation fails, and one write CU and one read CU are consumed.

Operation result description

Responses vary based on whether an operation is successful.
  • If an operation is successful, Tablestore returns the number of CUs that are consumed by the operation.
    Note Write operations consume read CUs based on the conditions that you specify.
    You can specify the condition field in the write request for a single row to determine whether to perform a row existence check before the write operation is performed. The following table describes valid values of the condition field.
    condition Description
    IGNORE No row existence check is performed.
    EXPECT_EXIST The row is expected to exist.
    • If the row exists, the operation is successful.
    • If the row does not exist, the operation fails.
    EXPECT_NOT_EXIST The row is expected to not exist.
    • If the row does not exist, the operation is successful.
    • If the row exists, the operation fails.
    Note If you set condition to EXPECT_NOT_EXIST in a DeleteRow or UpdateRow operation, the operation is invalid because rows that do not exist cannot be deleted. To update a row that does not exist, you can use the PutRow operation.
  • If errors occur, Tablestore returns the specific error codes. For example, a parameter fails the check, excessive data exists in a row, or a row existence check fails.

Parameters

Parameter Description
tableName The name of the data table.
primaryKey The primary key of the row.
Note
  • The number and types of the primary key columns that you specify must be the same as the actual number and types of primary key columns in the data 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 Auto-increment of primary key columns.
condition The condition that you want to specify to perform the PutRow operation. You can specify a row existence condition or a condition based on column values. For more information, see Conditional update.
Note
  • RowExistenceExpectation.IGNORE indicates 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 indicates that new data is inserted only when the specified row exists. The existing data is overwritten.
  • RowExistenceExpectation.EXPECT_NOT_EXIST indicates 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 parameters in the following sequence: the attribute column name, attribute column value (ColumnValue), attribute column value type (ColumnType), and timestamp. ColumnType and the timestamp are optional.
  • You can set ColumnType to ColumnType.INTEGER that specifies an INTEGER value, ColumnType.STRING that specifies a UTF-8 encoded STRING, ColumnType.BINARY that specifies a BINARY value, ColumnType.BOOLEAN that specifies a BOOLEAN value, or ColumnType.DOUBLE that specifies a DOUBLE value. If you want to set the column value type to BINARY, you must set ColumnType to ColumnType.BINARY. If you want to use other types of column values, the ColumnType is optional.
  • The timestamp is the data version number. For more information, see Data versions and TTL.

    You can specify a data version number or use the data version number that is generated by Tablestore. If you do not configure this parameter, the data version number that is generated by Tablestore is used.

    • The version number that is generated by Tablestore is the number of milliseconds that have elapsed since 00:00:00 UTC on January 1, 1970.
    • If you specify the 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

  • Example 1

    The following code provides an example on how to write a row that contains 10 attribute columns, each of which stores data of only one version. The version numbers (timestamps) are generated by Tablestore.

    private static void putRow(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 data 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));
    }
                        
  • Example 2

    The following 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, you need to specify the version numbers (timestamps).

    private static void putRow(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 data 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));
    }
                        
  • Example 3

    The following 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, you need to specify the version numbers (timestamps).

    private static void putRow(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 data 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));
    }
                        
  • Example 4

    The following 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, you need to specify the version numbers (timestamps).

    private static void putRow(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 data table. 
        RowPutChange rowPutChange = new RowPutChange(TABLE_NAME, primaryKey);
    
        // Specify a condition for the PutRow operation. In this example, a row is inserted only when the row exists and the value of the Col0 column is 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 or delete attribute columns from a row, delete a specified version of data from an attribute column, or update the existing data in an attribute column. If the row does not exist, a new row is added.
Note If you call the UpdateRow operation only to delete columns from a row and the row does not exist, no row is inserted into the table.

CU consumption

The number of read and write CUs that are consumed by a UpdateRow operation is calculated based on the following rules:
  • The number of consumed write CUs is rounded up from the calculation results of the following formula: Number of consumed write CUs = (Size of the data in all primary key columns of the row + Size of the data in the updated attribute columns)/4 KB.

    If the UpdateRow request contains deletion instructions for specified attribute columns, the length of the name of each attribute column that you want to delete is used as the column size.

  • If the value of the condition field is not IGNORE, the UpdateRow operation consumes read CUs. The number of consumed read CUs is rounded up from the calculation results of the following formula: Number of consumed read CUs = Size of the data in all primary key columns of the row/4 KB.
  • If row existence conditions are not met, the operation fails, and one write CU and one read CU are consumed.

Parameters

Parameter Description
tableName The name of the data table.
primaryKey The primary key of the row.
Note The number and types of the 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 condition that you want to specify to perform the UpdateRow operation. You can specify a row existence condition or a condition based on column values. For more information, see Conditional update.
column The attribute column that you want to update.
  • Each attribute column is specified by parameters in the following sequence: the attribute column name, attribute column value, attribute column value type, and timestamp. The attribute column value type and the timestamp are optional.

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

    • The version number that is generated by Tablestore is the number of milliseconds that have elapsed since 00:00:00 UTC on January 1, 1970.
    • If you specify the 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 that indicates a specified version of data. Unit: milliseconds.

  • To delete an attribute column, you need to only specify the attribute column name.
    Note A row exists even if all attribute columns in the row are deleted. To delete a row, use the DeleteRow operation.

Examples

  • Example 1

    The following code provides an example on how to update multiple columns, delete the specified version of a column, and delete the specified 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 data 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 specified version of a column. 
        rowUpdateChange.deleteColumn("Col10", 1465373223000L);
    
        // Delete a column. 
        rowUpdateChange.deleteColumns("Col11");
    
        client.updateRow(new UpdateRowRequest(rowUpdateChange));
    }                   
  • Example 2

    The following code provides an example on how to specify a condition for the UpdateRow operation:

    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 data table. 
        RowUpdateChange rowUpdateChange = new RowUpdateChange(TABLE_NAME, primaryKey);
    
        // Specify a condition for the UpdateRow operation. In this example, a row is updated only when the row exists and the value of the Col0 column is 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 specified version of a column. 
        rowUpdateChange.deleteColumn("Col10", 1465373223000L);
    
        // Delete 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 to one or more tables in a batch. The BatchWriteRow operation is a set of PutRow, UpdateRow, or DeleteRow operations. When you call the BatchWriteRow operation, the process of constructing the PutRow, UpdateRow, or DeleteRow operations is the same as the process of constructing the PutRow, UpdateRow, or DeleteRow operation when you call the PutRow, UpdateRow, or DeleteRow operation. BatchWriteRow supports conditional update.

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

Usage notes

When you call the BatchWriteRow operation to write multiple rows in a batch, some rows may fail to be written. If this happens, Tablestore does not return exceptions, but returns BatchWriteRowResponse in which the indexes and error messages of the failed rows are 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, the BatchWriteRow operation may return an exception about parameter errors before the first operation in the request is performed.

Examples

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

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

    // Construct rowPutChange1. 
    PrimaryKeyBuilder pk1Builder = PrimaryKeyBuilder.createPrimaryKeyBuilder();
    pk1Builder.addPrimaryKeyColumn(PRIMARY_KEY_NAME, PrimaryKeyValue.fromString("pk1"));
    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(PRIMARY_KEY_NAME, PrimaryKeyValue.fromString("pk2"));
    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(PRIMARY_KEY_NAME, PrimaryKeyValue.fromString("pk3"));
    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)));
    }
    // Delete 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(PRIMARY_KEY_NAME, PrimaryKeyValue.fromString("pk4"));
    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. In this example, only the retry request is constructed. 
         * We recommend that you use the custom retry policy in Tablestore SDKs as the retry method. You can use this feature to retry failed rows after batch operations are performed. After you configure the retry policy, you do not need to add retry code to call the operation. 
         */
        BatchWriteRowRequest retryRequest = batchWriteRowRequest.createRequestForRetry(response.getFailedRows());
    }
}