表格存储提供了PutRow、GetRow、UpdateRow和DeleteRow等单行操作的接口。

如需了解表格存储各场景的应用案例,请参见适用场景

前提条件

  • 已初始化Client,详情请参见初始化
  • 已创建数据表并写入数据。

插入一行数据(PutRow)

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 行的属性列。
    • 每一项的顺序是属性名、属性类型(可选)、属性值、时间戳(可选)。
    • 时间戳即数据的版本号,详情请参见数据版本和生命周期

      数据的版本号可以由系统自动生成或者自定义,如果不设置此参数,则默认由系统自动生成。

      • 当由系统自动生成数据的版本号时,系统默认将当前时间的毫秒单位时间戳(从1970-01-01 00:00:00 UTC计算起的毫秒数)作为数据的版本号。
      • 当自定义数据的版本号时,版本号需要为64位的毫秒单位时间戳且在有效版本范围内。
    condition 支持使用条件更新,可以设置原行的存在性条件或者原行中某列的列值条件,详情请参见条件更新
    说明
    • 从.NET SDK 2.2.0版本开始,Condition不仅支持行条件,也支持列条件。
    • Condition.IGNORE、Condition.EXPECT_EXIST和Condition.EXPECT_NOT_EXIST从.NET SDK 3.0.0版本开始被废弃,请替换为new Condition (RowExistenceExpectation.IGNORE)、new Condition (RowExistenceExpectation.EXPECT_EXIST)和new Condition (RowExistenceExpectation.EXPECT_NOT_EXIST)。
    • RowExistenceExpectation.IGNORE表示无论此行是否存在均会插入新数据,如果之前行已存在,则写入数据时会覆盖原有数据。
    • RowExistenceExpectation.EXPECT_EXIST表示只有此行存在时才会插入新数据,写入数据时会覆盖原有数据。
    • RowExistenceExpectation.EXPECT_NOT_EXIST表示只有此行不存在时才会插入数据。
  • 示例1

    插入一行数据。

        //定义行的主键,必须与创建表时的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

  • 示例2

    设置条件插入一行数据。如下示例的条件为当行存在且col1大于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));
    
                var request = new PutRowRequest(tableName, new Condition(RowExistenceExpectation.EXPECT_EXIST),
                                    primaryKey, attribute);
    
        //当col0列的值大于24时,允许再次插入行,覆盖掉原值。
        try
        {
            request.Condition.ColumnCondition = new RelationalCondition("col0",
                                                RelationalCondition.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

  • 示例3

    异步插入一行数据。

    注意 每一个异步调用都会启动一个线程,如果连续启动了很多异步调用,且每个都耗时比较大时,可能会出现超时。
        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(TableName, new Condition(RowExistenceExpectation.IGNORE),
                                                primaryKey, attribute);
    
                putRowTaskList.Add(TabeStoreClient.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

读取一行数据(GetRow)

GetRow接口用于读取一行数据。

读取的结果可能有如下两种:
  • 如果该行存在,则返回该行的各主键列以及属性列。
  • 如果该行不存在,则返回中不包含行,并且不会报错。
  • 接口
    /// <summary>
    /// 根据给定的主键读取单行数据。
    /// </summary>
    /// <param name="request">查询数据的请求</param>
    /// <returns>GetRow的响应</returns>
    public GetRowResponse GetRow(GetRowRequest request);
    
    /// <summary>
    /// GetRow的异步形式。
    /// </summary>
    public Task<GetRowResponse> GetRowAsync(GetRowRequest request);
                
  • 参数
    参数 说明
    tableName 数据表名称。
    primaryKey 行的主键。
    说明 设置的主键个数和类型必须和数据表的主键个数和类型一致。
    columnsToGet 读取的列集合,列名可以是主键列或属性列。

    如果不设置返回的列名,则返回整行数据。

    说明
    • 查询一行数据时,默认返回此行所有列的数据。如果需要只返回特定行,可以通过设置columnsToGet参数限制。如果将col0和col1加入到columnsToGet中,则只返回col0和col1列的值。
    • 当columnsToGet和filter同时使用时,执行顺序是先获取columnsToGet指定的列,再在返回的列中进行条件过滤。
    maxVersions 最多读取的版本数。
    说明 maxVersions与timeRange必须至少设置一个。
    • 如果仅设置maxVersions,则返回所有版本中从新到旧最多指定数量版本的数据。
    • 如果仅设置timeRange,则返回该范围内所有数据或指定版本数据。
    • 如果同时设置maxVersions和timeRange,则返回版本号范围内从新到旧最多指定数量版本的数据。
    timeRange 读取版本号范围或特定版本号的数据。详情请参见TimeRange
    说明 maxVersions与timeRange必须至少设置一个。
    • 如果仅设置maxVersions,则返回所有版本中从新到旧最多指定数量版本的数据。
    • 如果仅设置timeRange,则返回该范围内所有数据或指定版本数据。
    • 如果同时设置maxVersions和timeRange,则返回版本号范围内从新到旧最多指定数量版本的数据。
    • 如果查询一个范围的数据,则需要设置StartTime和EndTime。StartTime和EndTime分别表示起始时间戳和结束时间戳,范围为前闭后开区间,即[StartTime, EndTime)。
    • 如果查询特定版本号的数据,则需要设置SpecificTime。SpecificTime表示特定的时间戳。

    SpecificTime和[StartTime, EndTime)中只需要设置一个。

    时间戳的单位为毫秒,最小值为0,最大值为Int64.MaxValue。

    filter 使用过滤器,在服务端对读取结果再进行一次过滤,只返回符合过滤器中条件的数据行,详情请参见过滤器
    说明 当columnsToGet和filter同时使用时,执行顺序是先获取columnsToGet指定的列,再在返回的列中进行条件过滤。
  • 示例1

    读取一行数据。

        //定义行的主键,必须与创建表时的TableMeta中定义的一致。
        PrimaryKey primaryKey = new PrimaryKey();
        primaryKey.Add("pk0", new ColumnValue(0));
        primaryKey.Add("pk1", new ColumnValue("abc"));
    
        try
        {
            //构造查询请求对象,此处未指定读取的列,默认读取整行数据。
            var request = new GetRowRequest(TableName, primaryKey);
    
            //调用GetRow接口查询数据。
            var response = otsClient.GetRow(request);
    
            //输出此行的数据,此处省略,详见示例代码的GitHub链接。
    
            //如果没有抛出异常,则说明执行成功。
            Console.WriteLine("Get row succeeded.");
        }
        catch (Exception ex)
        {
            //如果抛出异常,则说明执行失败,处理异常。
            Console.WriteLine("Update table failed, exception:{0}", ex.Message);
        }
                

    详细代码请参见GetRow@GitHub

  • 示例2

    使用过滤器读取一行数据。

    如下示例为查询数据后,只返回col0和col1的数据,同时在col0列和col1列进行过滤,过滤条件是col0等于5或者col1不等于ff。

        //定义行的主键,必须与创建表时的TableMeta中定义的一致。
        PrimaryKey primaryKey = new PrimaryKey();
        primaryKey.Add("pk0", new ColumnValue(0));
        primaryKey.Add("pk1", new ColumnValue("abc"));
    
        var rowQueryCriteria = new SingleRowQueryCriteria("SampleTable");
        rowQueryCriteria.RowPrimaryKey = primaryKey;
    
        //条件1为col0列的值等于5。
        var filter1 = new RelationalCondition("col0",
                    RelationalCondition.CompareOperator.EQUAL,
                    new ColumnValue(5));
    
        //条件2为col1列的值不等于ff。
        var filter2 = new RelationalCondition("col1", RelationalCondition.CompareOperator.NOT_EQUAL, new ColumnValue("ff"));
    
        //构造组合条件,包括条件1和条件2,关系是OR。
        var filter = new CompositeCondition(CompositeCondition.LogicOperator.OR);
        filter.AddCondition(filter1);
        filter.AddCondition(filter2);
    
        rowQueryCriteria.Filter = filter;
    
        //设置要查询和返回的行,查询和过滤的顺序是先在行的[col0,col1]列上查询,然后再按条件过滤。
        rowQueryCriteria.AddColumnsToGet("col0");
        rowQueryCriteria.AddColumnsToGet("col1");
    
        //构造GetRowRequest。
        var request = new GetRowRequest(rowQueryCriteria);
    
        try
        {
            //查询。
            var response = otsClient.GetRow(request);
    
            //输出数据或者相关逻辑操作,此处省略。
    
            //如果没有抛出异常,则说明执行成功。
            Console.WriteLine("Get row with filter succeeded.");
        }
        catch (Exception ex)
        {
            //如果抛出异常,则说明执行失败,处理异常。
            Console.WriteLine("Get row with filter failed, exception:{0}", ex.Message);
        }
                

    详细代码请参见GetRowWithFilter@GitHub

更新一行数据(UpdateRow)

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 更新的属性列。
    • 增加或更新数据时,需要设置属性名、属性值、属性类型(可选)、时间戳(可选)。

      时间戳即数据的版本号,可以由系统自动生成或者自定义,如果不设置此参数,则默认由系统自动生成。详情请参见数据版本和生命周期

      • 当由系统自动生成数据的版本号时,系统默认将当前时间的毫秒单位时间戳(从1970-01-01 00:00:00 UTC计算起的毫秒数)作为数据的版本号。
      • 当自定义数据的版本号时,版本号需要为64位的毫秒单位时间戳且在有效版本范围内。
    • 删除属性列特定版本的数据时,只需要设置属性名和时间戳。

      时间戳是64位整数,单位为毫秒,表示某个特定版本的数据。

    • 删除属性列时,只需要设置属性名。
      说明 删除一行的全部属性列不等同于删除该行,如果需要删除该行,请使用DeleteRow操作。
  • 示例

    更新一行数据。

        //定义行的主键,必须与创建表时的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(TableName, 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

删除一行数据(DeleteRow)

DeleteRow接口用于删除一行数据。如果删除的行不存在,则不会发生任何变化。

  • 接口
        /// <summary>
        /// 指定数据表名称和行的主键,删除一行数据。
        /// </summary>
        /// <param name="request">请求实例</param>
        /// <returns>响应实例</returns>
        public DeleteRowResponse DeleteRow(DeleteRowRequest request);
    
        /// <summary>
        /// DeleteRow的异步形式。
        /// </summary>
        public Task<DeleteRowResponse> DeleteRowAsync(DeleteRowRequest request);
                
  • 参数
    参数 说明
    tableName 数据表名称。
    primaryKey 行的主键。
    说明 设置的主键个数和类型必须和数据表的主键个数和类型一致。
    condition 使用条件更新,可以设置原行的存在性条件或者原行中某列的列值条件,详情请参见条件更新
  • 示例

    删除一行数据。

        //要删除的行的PK列分别为0和"abc"。
        var primaryKey = new PrimaryKey();
        primaryKey.Add("pk0", new ColumnValue(0));
        primaryKey.Add("pk1", new ColumnValue("abc"));
    
        try
        {
            //构造请求,RowExistenceExpectation.EXPECT_EXIST表示只有此行存在时才执行删除。
            var deleteRowRequest = new DeleteRowRequest("SampleTable", new Condition(RowExistenceExpectation.EXPECT_EXIST), primaryKey);
    
            //调用DeleteRow接口删除数据。
            otsClient.DeleteRow(deleteRowRequest);
    
            //如果没有抛出异常,则说明执行成功。
            Console.Writeline("Delete table succeeded.");
        }
        catch (Exception ex)
        {
            //如果抛出异常,则说明执行失败,处理异常。
            Console.WriteLine("Delete table failed, exception:{0}", ex.Message);
        }
                

    详细代码请参见DeleteRow@GitHub