表格存储提供了单行插入、单行更新和批量写入的写入方式用于写入数据到数据表。当要写入数据到数据表时,您需要指定完整主键以及要增删改的属性列。在高并发应用中写入数据时,您可以配置行存在性条件或者列条件实现按照指定条件更新数据。
如果需要了解表格存储各场景的应用案例,请参见快速玩转Tablestore入门与实战。
写入方式
表格存储提供的数据写入接口包括PutRow、UpdateRow和BatchWriteRow。写入数据时,请根据实际场景选择相应写入方式。
写入方式 | 说明 | 适用场景 |
调用PutRow接口新写入一行数据。如果该行已存在,则表格存储会先删除原行数据(原行的所有列以及所有版本的数据),再写入新行数据。 | 适用于要写入数据较少的场景。 | |
调用UpdateRow接口更新一行数据,支持增加和删除一行中的属性列,删除属性列指定版本的数据,或者更新已存在的属性列值。如果更新的行不存在,则新增一行数据。 | 适用于更新已写入数据的场景,例如删除属性列、删除某个数据版本、修改属性列值等。 | |
调用BatchWriteRow接口在一次请求中进行批量写入操作或者一次对多张表进行写入。 BatchWriteRow操作由多个PutRow、UpdateRow、DeleteRow子操作组成,构造子操作的过程与使用PutRow接口、UpdateRow接口和DeleteRow接口时相同。 | 适用于要写入、删除或者更新大量数据以及要同时进行增删改数据的场景。 |
前提条件
已初始化Client,具体操作,请参见初始化OTSClient。
插入单行数据
调用PutRow接口新写入一行数据。如果该行已存在,则先删除原行数据(原行的所有列以及所有版本的数据),再写入新行数据。
接口
/// <summary>
/// 指定数据表名称、主键和属性,写入一行数据。返回本次操作消耗的CapacityUnit。
/// </summary>
/// <param name="request">插入数据的请求</param>
/// <returns>本次操作消耗的CapacityUnit</returns>
public PutRowResponse PutRow(PutRowRequest request);
/// <summary>
/// PutRow的异步形式。
/// </summary>
public Task<PutRowResponse> PutRowAsync(PutRowRequest request);
参数
参数 | 说明 |
tableName | 数据表名称。 |
primaryKey | 行的主键。主键包括主键列名、主键类型和主键值。 重要
|
attribute | 行的属性列。每一项的顺序是属性名、属性类型(可选)、属性值、时间戳(可选)。 |
condition | 使用条件更新,可以设置原行的存在性条件或者原行中某列的列值条件。更多信息,请参见条件更新。 说明
|
示例
插入一行数据
以下示例用于插入一行数据。
//定义行的主键,必须与创建表时的TableMeta中定义的一致。
var primaryKey = new PrimaryKey();
primaryKey.Add("pk0", new ColumnValue(0));
primaryKey.Add("pk1", new ColumnValue("abc"));
//定义要写入该行的属性列。
var attribute = new AttributeColumns();
attribute.Add("col0", new ColumnValue(0));
attribute.Add("col1", new ColumnValue("a"));
attribute.Add("col2", new ColumnValue(true));
try
{
//构造插入数据的请求对象,RowExistenceExpectation.IGNORE表示无论此行是否存在均会插入新数据。
var request = new PutRowRequest("SampleTable", new Condition(RowExistenceExpectation.IGNORE),
primaryKey, attribute);
//调用PutRow接口插入数据。
otsClient.PutRow(request);
//如果没有抛出异常,则说明执行成功。
Console.WriteLine("Put row succeeded.");
}
catch (Exception ex)
{
//如果抛出异常,则说明执行失败,处理异常。
Console.WriteLine("Put row failed, exception:{0}", ex.Message);
}
详细代码请参见PutRow@GitHub。
插入数据时使用列条件和行条件
以下示例用于当行存在且col0大于24时才执行插入操作。
//定义行的主键,必须与创建表时的TableMeta中定义的一致。
var primaryKey = new PrimaryKey();
primaryKey.Add("pk0", new ColumnValue(0));
primaryKey.Add("pk1", new ColumnValue("abc"));
//定义要写入该行的属性列。
AttributeColumns attribute = new AttributeColumns();
attribute.Add("col0", new ColumnValue(0));
attribute.Add("col1", new ColumnValue("a"));
attribute.Add("col2", new ColumnValue(true));
//当col0列的值大于24时,允许再次插入行,覆盖掉原值。
try
{
var request = new PutRowRequest("SampleTable", new Condition(RowExistenceExpectation.EXPECT_EXIST),
primaryKey, attribute);
request.Condition.ColumnCondition = new RelationalCondition("col0",
CompareOperator.GREATER_THAN,
new ColumnValue(24));
otsClient.PutRow(request);
Console.WriteLine("Put row succeeded.");
}
catch (Exception ex)
{
Console.WriteLine("Put row failed. error:{0}", ex.Message);
}
详细代码请参见ConditionPutRow@GitHub。
异步插入数据
以下示例用于异步插入多行数据。
每一个异步调用都会启动一个线程,如果连续启动了很多异步调用,且每个都耗时比较大时,可能会出现超时。
try
{
var putRowTaskList = new List<Task<PutRowResponse>>();
for (int i = 0; i < 100; i++)
{
//定义行的主键,必须与创建表时的TableMeta中定义的一致。
var primaryKey = new PrimaryKey();
primaryKey.Add("pk0", new ColumnValue(i));
primaryKey.Add("pk1", new ColumnValue("abc"));
//定义要写入该行的属性列。
var attribute = new AttributeColumns();
attribute.Add("col0", new ColumnValue(i));
attribute.Add("col1", new ColumnValue("a"));
attribute.Add("col2", new ColumnValue(true));
var request = new PutRowRequest("SampleTable", new Condition(RowExistenceExpectation.IGNORE),
primaryKey, attribute);
putRowTaskList.Add(otsClient.PutRowAsync(request));
}
//等待每个异步调用返回,并打印出消耗的CU值。
foreach (var task in putRowTaskList)
{
task.Wait();
Console.WriteLine("consumed read:{0}, write:{1}", task.Result.ConsumedCapacityUnit.Read,
task.Result.ConsumedCapacityUnit.Write);
}
//如果没有抛出异常,则说明执行成功。
Console.WriteLine("Put row async succeeded.");
}
catch (Exception ex)
{
//如果抛出异常,则说明执行失败,处理异常。
Console.WriteLine("Put row async failed. exception:{0}", ex.Message);
}
详细代码请参见PutRowAsync@GitHub。
更新单行数据
调用UpdateRow接口更新一行数据,可以增加和删除一行中的属性列,删除属性列指定版本的数据,或者更新已存在的属性列的值。如果更新的行不存在,则新增一行数据。
当UpdateRow请求中只包含删除指定的列且该行不存在时,则该请求不会新增一行数据。
接口
/// <summary>
/// 更新指定行的数据,如果该行不存在,则新增一行;若该行存在,则根据请求的内容在该行中新增、修改或者删除指定列的值。
/// </summary>
/// <param name="request">请求实例</param>
public UpdateRowResponse UpdateRow(UpdateRowRequest request);
/// <summary>
/// UpdateRow的异步形式。
/// </summary>
/// <param name="request"></param>
/// <returns></returns>
public Task<UpdateRowResponse> UpdateRowAsync(UpdateRowRequest request);
参数
参数 | 说明 |
tableName | 数据表名称。 |
primaryKey | 行的主键。主键包括主键列名、主键类型和主键值。 重要 设置的主键个数和类型必须和数据表的主键个数和类型一致。 |
condition | 使用条件更新,可以设置原行的存在性条件或者原行中某列的列值条件。更多信息,请参见条件更新。 |
attribute | 更新的属性列。
|
示例
以下示例用于更新一行数据。
//定义行的主键,必须与创建表时的TableMeta中定义的一致。
PrimaryKey primaryKey = new PrimaryKey();
primaryKey.Add("pk0", new ColumnValue(0));
primaryKey.Add("pk1", new ColumnValue("abc"));
//定义要写入该行的属性列。
UpdateOfAttribute attribute = new UpdateOfAttribute();
attribute.AddAttributeColumnToPut("col0", new ColumnValue(0));
attribute.AddAttributeColumnToPut("col1", new ColumnValue("b")); // 将原先的值'a'改为'b'
attribute.AddAttributeColumnToPut("col2", new ColumnValue(true));
try
{
//构造更新行的请求对象,RowExistenceExpectation.IGNORE表示无论此行是否存在都执行更新。
var request = new UpdateRowRequest("SampleTable", new Condition(RowExistenceExpectation.IGNORE),
primaryKey, attribute);
//调用UpdateRow接口更新数据。
otsClient.UpdateRow(request);
//如果没有抛出异常,则说明执行成功。
Console.WriteLine("Update row succeeded.");
}
catch (Exception ex)
{
//如果抛出异常,则说明执行失败,处理异常。
Console.WriteLine("Update row failed, exception:{0}", ex.Message);
}
详细代码请参见UpdateRow@GitHub。
批量写入数据
调用BatchWriteRow接口在一次请求中进行批量写入操作或者一次对多张表进行写入。
BatchWriteRow操作由多个PutRow、UpdateRow、DeleteRow子操作组成,构造子操作的过程与使用PutRow接口、UpdateRow接口和DeleteRow接口时相同。
BatchWriteRow的各个子操作独立执行,表格存储会分别返回各个子操作的执行结果。
注意事项
由于批量写入可能存在部分行失败的情况,失败行的Index及错误信息在返回的BatchWriteRowResponse中,但并不抛出异常。因此调用BatchWriteRow接口时,需要检查返回值,可通过BatchWriteRowResponse的isAllSucceed方法判断是否全部成功;如果不检查返回值,则可能会忽略掉部分操作的失败。
当服务端检查到某些操作出现参数错误时,BatchWriteRow接口可能会抛出参数错误的异常,此时该请求中所有的操作都未执行。
接口
/// <summary>
/// <para>批量插入,修改或删除一个或多个表中的若干行数据。</para>
/// <para>BatchWriteRow操作可视为多个PutRow、UpdateRow、DeleteRow操作的集合,各个操作独立执行,独立返回结果,独立计算服务能力单元。</para>
/// <para>与执行大量的单行写操作相比,使用BatchWriteRow操作可以有效减少请求的响应时间,提高数据的写入速率。</para>
/// </summary>
/// <param name="request">请求实例</param>
/// <returns>响应实例</returns>
public BatchWriteRowResponse BatchWriteRow(BatchWriteRowRequest request);
/// <summary>
/// BatchWriteRow的异步形式。
/// </summary>
/// <param name="request"></param>
/// <returns></returns>
public Task<BatchWriteRowResponse> BatchWriteRowAsync(BatchWriteRowRequest request);
示例
以下示例用于批量写入100行数据。
var TableName = "SampleTable";
//构造批量写的请求对象,设置100行数据的主键。
var request = new BatchWriteRowRequest();
var rowChanges = new RowChanges(TableName);
for (int i = 0; i < 100; i++)
{
PrimaryKey primaryKey = new PrimaryKey();
primaryKey.Add("pk0", new ColumnValue(i));
primaryKey.Add("pk1", new ColumnValue("abc"));
//定义要写入该行的属性列。
UpdateOfAttribute attribute = new UpdateOfAttribute();
attribute.AddAttributeColumnToPut("col0", new ColumnValue(0));
attribute.AddAttributeColumnToPut("col1", new ColumnValue("a"));
attribute.AddAttributeColumnToPut("col2", new ColumnValue(true));
rowChanges.AddUpdate(new Condition(RowExistenceExpectation.IGNORE), primaryKey, attribute);
}
request.Add(TableName, rowChanges);
try
{
//调用BatchWriteRow接口写入数据。
var response = otsClient.BatchWriteRow(request);
var tableRows = response.TableRespones;
var rows = tableRows[TableName];
//批量操作可能部分成功部分失败,需要检查每行的状态是否成功,详见示例代码的GitHub链接。
}
catch (Exception ex)
{
//如果抛出异常,则说明执行失败,处理异常。
Console.WriteLine("Batch put row failed, exception:{0}", ex.Message);
}
详细代码请参见BatchWriteRow@GitHub。