Tablestore提供了PutRow和UpdateRow介面用於寫入單行資料以及BatchWriteRow介面用於批量寫入資料。

说明 組成表的基本單位為行,行由主鍵和屬性群組成。其中主鍵是必須的,且每一行的主鍵列的名稱和類型相同;屬性不是必須的,且每一行的屬性可以不同。更多資訊,請參見模型介紹

使用

您可以使用如下語言的SDK寫入資料。

插入單行資料

調用PutRow介面新寫入一行資料。如果該行已存在,則先刪除原行資料(原行的所有列以及所有版本的資料),再寫入新行資料。

CU消耗說明

PutRow操作消耗的讀CU和寫CU說明如下:
  • 消耗的寫CU為修改的行主鍵資料大小與屬性列資料大小之和除以4 KB向上取整。
  • 如果指定條件檢查不為IGNORE,則消耗行主鍵資料大小除以4 KB向上取整的讀CU。
  • 如果操作不滿足指定的行存在性檢查條件,則操作失敗並消耗1單位寫CU和1單位讀CU。

操作結果說明

不同的操作結果返回的結果不同。
  • 如果操作成功,Tablestore會返回操作消耗的服務能力單元(CU)。
    说明 寫入操作會根據指定的condition情況消耗一定的讀CU。
    通過在單行寫入請求中設定condition欄位可以指定寫入操作執行時,是否對行的存在性進行檢查。condition有如下三種類型:
    condition 說明
    IGNORE 不做任何存在性檢查。
    EXPECT_EXIST 期望行存在。
    • 如果該行存在,則操作成功。
    • 如果該行不存在,則操作失敗。
    EXPECT_NOT_EXIST 期望行不存在。
    • 如果該行不存在,則操作成功。
    • 如果該行存在,則操作失敗。
    说明 condition為EXPECT_NOT_EXIST的DeleteRow、UpdateRow操作是無意義的,即刪除一個不存在的行是無意義的。如果需要更新不存在的行可以使用PutRow操作。
  • 如果操作發生錯誤,例如參數檢查失敗、單行資料量過多、行存在性檢查失敗等,Tablestore會返回錯誤碼。

參數

參數 說明
tableName 資料表名稱。
primaryKey 行的主鍵。
说明
  • 設定的主鍵個數和類型必須和資料表的主鍵個數和類型一致。
  • 當主鍵為自增列時,只需將自增列的值設定為預留位置。更多資訊,請參見主鍵列自增
condition 使用條件更新,可以設定原行的存在性條件或者原行中某列的列值條件。更多資訊,請參見條件更新
说明
  • RowExistenceExpectation.IGNORE表示無論此行是否存在均會插入新資料,如果之前行已存在,則寫入資料時會覆蓋原有資料。
  • RowExistenceExpectation.EXPECT_EXIST表示只有此行存在時才會插入新資料,寫入資料時會覆蓋原有資料。
  • RowExistenceExpectation.EXPECT_NOT_EXIST表示只有此行不存在時才會插入資料。
column 行的屬性列。
  • 每一項的順序是屬性名稱、屬性值ColumnValue、屬性類型ColumnType(可選)、時間戳記(可選)。
  • ColumnType可以是INTEGER、STRING(UTF-8編碼字串)、BINARY、BOOLEAN、DOUBLE五種,分別用ColumnType.INTEGER、ColumnType.STRING、ColumnType.BINARY、ColumnType.BOOLEAN、ColumnType.DOUBLE表示,其中BINARY不可省略,其他類型都可以省略。
  • 時間戳記即資料的版本號碼。更多資訊,請參見資料版本和生命週期

    資料的版本號碼可以由系統自動產生或者自訂,如果不設定此參數,則預設由系統自動產生。

    • 當由系統自動產生資料的版本號碼時,系統預設將目前時間的毫秒單位時間戳記(從1970-01-01 00:00:00 UTC計算起的毫秒數)作為資料的版本號碼。
    • 當自訂資料的版本號碼時,版本號碼需要為64位的毫秒單位時間戳記且在有效版本範圍內。

樣本

  • 樣本1

    寫入10列屬性列,每列寫入1個版本,由系統自動產生資料的版本號碼(時間戳記)。

    private static void putRow(SyncClient client, String pkValue) {
        //構造主鍵。
        PrimaryKeyBuilder primaryKeyBuilder = PrimaryKeyBuilder.createPrimaryKeyBuilder();
        primaryKeyBuilder.addPrimaryKeyColumn(PRIMARY_KEY_NAME, PrimaryKeyValue.fromString(pkValue));
        PrimaryKey primaryKey = primaryKeyBuilder.build();
        //設定資料表名稱。
        RowPutChange rowPutChange = new RowPutChange(TABLE_NAME, primaryKey);
    
        //加入一些屬性列。
        for (int i = 0; i < 10; i++) {
            rowPutChange.addColumn(new Column("Col" + i, ColumnValue.fromLong(i)));
        }
    
        client.putRow(new PutRowRequest(rowPutChange));
    }
                        
  • 樣本2

    寫入10列屬性列,每列寫入3個版本,自訂資料的版本號碼(時間戳記)。

    private static void putRow(SyncClient client, String pkValue) {
        //構造主鍵。
        PrimaryKeyBuilder primaryKeyBuilder = PrimaryKeyBuilder.createPrimaryKeyBuilder();
        primaryKeyBuilder.addPrimaryKeyColumn(PRIMARY_KEY_NAME, PrimaryKeyValue.fromString(pkValue));
        PrimaryKey primaryKey = primaryKeyBuilder.build();
        //設定資料表名稱。
        RowPutChange rowPutChange = new RowPutChange(TABLE_NAME, primaryKey);
    
        //加入一些屬性列。
        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));
    }
                        
  • 樣本3

    期望原行不存在時,寫入10列屬性列,每列寫入3個版本,自訂資料的版本號碼(時間戳記)。

    private static void putRow(SyncClient client, String pkValue) {
        //構造主鍵。
        PrimaryKeyBuilder primaryKeyBuilder = PrimaryKeyBuilder.createPrimaryKeyBuilder();
        primaryKeyBuilder.addPrimaryKeyColumn(PRIMARY_KEY_NAME, PrimaryKeyValue.fromString(pkValue));
        PrimaryKey primaryKey = primaryKeyBuilder.build();
        //設定資料表名稱。
        RowPutChange rowPutChange = new RowPutChange(TABLE_NAME, primaryKey);
    
        //設定條件更新,行條件檢查為期望原行不存在。
        rowPutChange.setCondition(new Condition(RowExistenceExpectation.EXPECT_NOT_EXIST));
    
        //加入一些屬性列。
        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));
    }
                        
  • 樣本4

    期望原行存在且Col0列的值大於100時,寫入10列屬性列,每列寫入3個版本,自訂資料的版本號碼(時間戳記)。

    private static void putRow(SyncClient client, String pkValue) {
        //構造主鍵。
        PrimaryKeyBuilder primaryKeyBuilder = PrimaryKeyBuilder.createPrimaryKeyBuilder();
        primaryKeyBuilder.addPrimaryKeyColumn(PRIMARY_KEY_NAME, PrimaryKeyValue.fromString(pkValue));
        PrimaryKey primaryKey = primaryKeyBuilder.build();
        //設定資料表名稱。
        RowPutChange rowPutChange = new RowPutChange(TABLE_NAME, primaryKey);
    
        //設定條件更新,期望原行存在且Col0列的值大於100時寫入資料。
        Condition condition = new Condition(RowExistenceExpectation.EXPECT_EXIST);
        condition.setColumnCondition(new SingleColumnValueCondition("Col0",
                SingleColumnValueCondition.CompareOperator.GREATER_THAN, ColumnValue.fromLong(100)));
        rowPutChange.setCondition(condition);
    
        //加入一些屬性列。
        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));
    }
                        

更新單行資料

調用UpdateRow介面更新一行資料,可以增加和刪除一行中的屬性列,刪除屬性列指定版本的資料,或者更新已存在的屬性列的值。如果更新的行不存在,則新增一行資料。
说明 當UpdateRow請求中只包含刪除指定的列且該行不存在時,則該請求不會新增一行資料。

CU消耗說明

UpdateRow操作消耗的讀CU和寫CU說明如下:
  • 消耗的寫CU為修改的行主鍵資料大小與屬性列資料大小之和除以4 KB向上取整。

    操作中包含的需要刪除的屬性列,只有屬性列的列名計入屬性列資料大小。

  • 如果指定條件檢查不為IGNORE,則消耗行主鍵資料大小除以4 KB向上取整的讀CU。
  • 如果操作不滿足指定的行存在性檢查條件,則操作失敗並消耗1單位寫CU和1單位讀CU。

參數

參數 說明
tableName 資料表名稱。
primaryKey 行的主鍵。
说明 設定的主鍵個數和類型必須和資料表的主鍵個數和類型一致。
condition 使用條件更新,可以設定原行的存在性條件或者原行中某列的列值條件。更多資訊,請參見條件更新
column 更新的屬性列。
  • 增加或更新資料時,需要設定屬性名稱、屬性值、屬性類型(可選)、時間戳記(可選)。

    時間戳記即資料的版本號碼,可以由系統自動產生或者自訂,如果不設定此參數,則預設由系統自動產生。更多資訊,請參見資料版本和生命週期

    • 當由系統自動產生資料的版本號碼時,系統預設將目前時間的毫秒單位時間戳記(從1970-01-01 00:00:00 UTC計算起的毫秒數)作為資料的版本號碼。
    • 當自訂資料的版本號碼時,版本號碼需要為64位的毫秒單位時間戳記且在有效版本範圍內。
  • 刪除屬性列特定版本的資料時,只需要設定屬性名稱和時間戳記。

    時間戳記是64位整數,單位為毫秒,表示某個特定版本的資料。

  • 刪除屬性列時,只需要設定屬性名稱。
    说明 刪除一行的全部屬性列不等同於刪除該行,如果需要刪除該行,請使用DeleteRow操作。

樣本

  • 樣本1

    更新一些列,刪除某列的某一版本資料,刪除某列。

    private static void updateRow(SyncClient client, String pkValue) {
        //構造主鍵。
        PrimaryKeyBuilder primaryKeyBuilder = PrimaryKeyBuilder.createPrimaryKeyBuilder();
        primaryKeyBuilder.addPrimaryKeyColumn(PRIMARY_KEY_NAME, PrimaryKeyValue.fromString(pkValue));
        PrimaryKey primaryKey = primaryKeyBuilder.build();
        //設定資料表名稱。
        RowUpdateChange rowUpdateChange = new RowUpdateChange(TABLE_NAME, primaryKey);
    
        //更新一些列。
        for (int i = 0; i < 10; i++) {
            rowUpdateChange.put(new Column("Col" + i, ColumnValue.fromLong(i)));
        }
    
        //刪除某列的某一版本。
        rowUpdateChange.deleteColumn("Col10", 1465373223000L);
    
        //刪除某一列。
        rowUpdateChange.deleteColumns("Col11");
    
        client.updateRow(new UpdateRowRequest(rowUpdateChange));
    }                   
  • 樣本2

    設定更新的條件。

    private static void updateRow(SyncClient client, String pkValue) {
        //構造主鍵。
        PrimaryKeyBuilder primaryKeyBuilder = PrimaryKeyBuilder.createPrimaryKeyBuilder();
        primaryKeyBuilder.addPrimaryKeyColumn(PRIMARY_KEY_NAME, PrimaryKeyValue.fromString(pkValue));
        PrimaryKey primaryKey = primaryKeyBuilder.build();
        //設定資料表名稱。
        RowUpdateChange rowUpdateChange = new RowUpdateChange(TABLE_NAME, primaryKey);
    
        //設定條件更新,期望原行存在且Col0列的值大於100時更新資料。
        Condition condition = new Condition(RowExistenceExpectation.EXPECT_EXIST);
        condition.setColumnCondition(new SingleColumnValueCondition("Col0",
                SingleColumnValueCondition.CompareOperator.GREATER_THAN, ColumnValue.fromLong(100)));
        rowUpdateChange.setCondition(condition);
    
        //更新一些列。
        for (int i = 0; i < 10; i++) {
            rowUpdateChange.put(new Column("Col" + i, ColumnValue.fromLong(i)));
        }
    
        //刪除某列的某一版本。
        rowUpdateChange.deleteColumn("Col10", 1465373223000L);
    
        //刪除某一列。
        rowUpdateChange.deleteColumns("Col11");
    
        client.updateRow(new UpdateRowRequest(rowUpdateChange));
    }             

批量寫入資料

調用BatchWriteRow介面在一次請求中進行批量的寫入操作,也支援一次對多張表進行寫入。BatchWriteRow操作由多個PutRow、UpdateRow、DeleteRow子操作組成,構造子操作的過程與使用PutRow介面、UpdateRow介面和DeleteRow介面時相同,也支援使用條件更新。

BatchWriteRow的各個子操作獨立執行,Tablestore會分別返回各個子操作的執行結果。

注意事項

由於批量寫入可能存在部分行失敗的情況,失敗行的Index及錯誤資訊在返回的BatchWriteRowResponse中,但並不拋出異常。因此調用BatchWriteRow介面時,需要檢查傳回值,可通過BatchWriteRowResponse的isAllSucceed方法判斷是否全部成功;如果不檢查傳回值,則可能會忽略掉部分操作的失敗。

當服務端檢查到某些操作出現參數錯誤時,BatchWriteRow介面可能會拋出參數錯誤的異常,此時該請求中所有的操作都未執行。

樣本

一次BatchWriteRow請求包含2個PutRow操作、1個UpdateRow操作和1個DeleteRow操作。

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

    //構造rowPutChange1。
    PrimaryKeyBuilder pk1Builder = PrimaryKeyBuilder.createPrimaryKeyBuilder();
    pk1Builder.addPrimaryKeyColumn(PRIMARY_KEY_NAME, PrimaryKeyValue.fromString("pk1"));
    RowPutChange rowPutChange1 = new RowPutChange(TABLE_NAME, pk1Builder.build());
    //添加一些列。
    for (int i = 0; i < 10; i++) {
        rowPutChange1.addColumn(new Column("Col" + i, ColumnValue.fromLong(i)));
    }
    //添加到batch操作中。
    batchWriteRowRequest.addRowChange(rowPutChange1);

    //構造rowPutChange2。
    PrimaryKeyBuilder pk2Builder = PrimaryKeyBuilder.createPrimaryKeyBuilder();
    pk2Builder.addPrimaryKeyColumn(PRIMARY_KEY_NAME, PrimaryKeyValue.fromString("pk2"));
    RowPutChange rowPutChange2 = new RowPutChange(TABLE_NAME, pk2Builder.build());
    //添加一些列。
    for (int i = 0; i < 10; i++) {
        rowPutChange2.addColumn(new Column("Col" + i, ColumnValue.fromLong(i)));
    }
    //添加到batch操作中。
    batchWriteRowRequest.addRowChange(rowPutChange2);

    //構造rowUpdateChange。
    PrimaryKeyBuilder pk3Builder = PrimaryKeyBuilder.createPrimaryKeyBuilder();
    pk3Builder.addPrimaryKeyColumn(PRIMARY_KEY_NAME, PrimaryKeyValue.fromString("pk3"));
    RowUpdateChange rowUpdateChange = new RowUpdateChange(TABLE_NAME, pk3Builder.build());
    //添加一些列。
    for (int i = 0; i < 10; i++) {
        rowUpdateChange.put(new Column("Col" + i, ColumnValue.fromLong(i)));
    }
    //刪除一列。
    rowUpdateChange.deleteColumns("Col10");
    //添加到batch操作中。
    batchWriteRowRequest.addRowChange(rowUpdateChange);

    //構造rowDeleteChange。
    PrimaryKeyBuilder pk4Builder = PrimaryKeyBuilder.createPrimaryKeyBuilder();
    pk4Builder.addPrimaryKeyColumn(PRIMARY_KEY_NAME, PrimaryKeyValue.fromString("pk4"));
    RowDeleteChange rowDeleteChange = new RowDeleteChange(TABLE_NAME, pk4Builder.build());
    //添加到batch操作中。
    batchWriteRowRequest.addRowChange(rowDeleteChange);

    BatchWriteRowResponse response = client.batchWriteRow(batchWriteRowRequest);

    System.out.println("是否全部成功:" + response.isAllSucceed());
    if (!response.isAllSucceed()) {
        for (BatchWriteRowResponse.RowResult rowResult : response.getFailedRows()) {
            System.out.println("失敗的行:" + batchWriteRowRequest.getRowChange(rowResult.getTableName(), rowResult.getIndex()).getPrimaryKey());
            System.out.println("失敗原因:" + rowResult.getError());
        }
        /**
         * 可以通過createRequestForRetry方法再構造一個請求對失敗的行進行重試。此處只給出構造重試請求的部分。
         * 推薦的重試方法是使用SDK的自訂重試策略功能,支援對batch操作的部分行錯誤進行重試。設定重試策略後,調用介面處無需增加重試代碼。
         */
        BatchWriteRowRequest retryRequest = batchWriteRowRequest.createRequestForRetry(response.getFailedRows());
    }
}