使用 PartiQL for DynamoDB 执行事务 - Amazon DynamoDB
Amazon Web Services 文档中描述的 Amazon Web Services 服务或功能可能因区域而异。要查看适用于中国区域的差异,请参阅 中国的 Amazon Web Services 服务入门 (PDF)

使用 PartiQL for DynamoDB 执行事务

本部分介绍如何使用事务和 PartiQL for DynamoDB。PartiQL 事务限制为总共 100 条语句(操作)。

有关 DynamoDB 事务的更多信息,请参阅使用 DynamoDB 事务管理复杂工作流

注意

整个事务必须由读取语句或写语句组成。您不能在一个事务中混合使用这两个语句。EXISTS 函数是一个例外。可用于检查项目的特定属性的条件,类似于 TransactWriteItems API 操作中 ConditionCheck 的方式。

语法

[ { "Statement":" statement ", "Parameters":[ { " parametertype " : " parametervalue " }, ...] } , ... ]

参数

语句

(必需)PartiQL for DynamoDB 支持的语句。

注意

整个事务必须由读取语句或写语句组成。您不能在一个事务中混合使用这两个语句。

parametertype

(可选)DynamoDB 类型,如果在指定 PartiQL 语句时使用了参数。

parametervalue

(可选)如果在指定 PartiQL 语句时使用了参数,则为参数值。

返回值

此语句不会返回写入操作(INSERT、UPDATE 或 DELETE)的任何值。但是,根据 WHERE 子句中指定的条件,它会为读取操作 (SELECT) 返回不同的值。

注意

如果任何单例 INSERT、UPDATE 或 DELETE 操作返回错误,则取消事务并抛出 TransactionCanceledException 异常,取消原因代码包括来自各个单例操作的错误。

示例

以下示例运行作为事务的多条语句。

Amazon CLI
  1. 将以下 JSON 代码保存到名为 partiql.json 的文件

    [ { "Statement": "EXISTS(SELECT * FROM \"Music\" where Artist='No One You Know' and SongTitle='Call Me Today' and Awards is MISSING)" }, { "Statement": "INSERT INTO Music value {'Artist':?,'SongTitle':'?'}", "Parameters": [{\"S\": \"Acme Band\"}, {\"S\": \"Best Song\"}] }, { "Statement": "UPDATE \"Music\" SET AwardsWon=1 SET AwardDetail={'Grammys':[2020, 2018]} where Artist='Acme Band' and SongTitle='PartiQL Rocks'" } ]
  2. 在命令提示符中运行以下命令。

    aws dynamodb execute-transaction --transact-statements file://partiql.json
Java
public class DynamoDBPartiqlTransaction { public static void main(String[] args) { // Create the DynamoDB Client with the region you want AmazonDynamoDB dynamoDB = createDynamoDbClient("us-west-2"); try { // Create ExecuteTransactionRequest ExecuteTransactionRequest executeTransactionRequest = createExecuteTransactionRequest(); ExecuteTransactionResult executeTransactionResult = dynamoDB.executeTransaction(executeTransactionRequest); System.out.println("ExecuteTransaction successful."); // Handle executeTransactionResult } catch (Exception e) { handleExecuteTransactionErrors(e); } } private static AmazonDynamoDB createDynamoDbClient(String region) { return AmazonDynamoDBClientBuilder.standard().withRegion(region).build(); } private static ExecuteTransactionRequest createExecuteTransactionRequest() { ExecuteTransactionRequest request = new ExecuteTransactionRequest(); // Create statements List<ParameterizedStatement> statements = getPartiQLTransactionStatements(); request.setTransactStatements(statements); return request; } private static List<ParameterizedStatement> getPartiQLTransactionStatements() { List<ParameterizedStatement> statements = new ArrayList<ParameterizedStatement>(); statements.add(new ParameterizedStatement() .withStatement("EXISTS(SELECT * FROM "Music" where Artist='No One You Know' and SongTitle='Call Me Today' and Awards is MISSING)")); statements.add(new ParameterizedStatement() .withStatement("INSERT INTO "Music" value {'Artist':'?','SongTitle':'?'}") .withParameters(new AttributeValue("Acme Band"),new AttributeValue("Best Song"))); statements.add(new ParameterizedStatement() .withStatement("UPDATE "Music" SET AwardsWon=1 SET AwardDetail={'Grammys':[2020, 2018]} where Artist='Acme Band' and SongTitle='PartiQL Rocks'")); return statements; } // Handles errors during ExecuteTransaction execution. Use recommendations in error messages below to add error handling specific to // your application use-case. private static void handleExecuteTransactionErrors(Exception exception) { try { throw exception; } catch (TransactionCanceledException tce) { System.out.println("Transaction Cancelled, implies a client issue, fix before retrying. Error: " + tce.getErrorMessage()); } catch (TransactionInProgressException tipe) { System.out.println("The transaction with the given request token is already in progress, consider changing " + "retry strategy for this type of error. Error: " + tipe.getErrorMessage()); } catch (IdempotentParameterMismatchException ipme) { System.out.println("Request rejected because it was retried with a different payload but with a request token that was already used, " + "change request token for this payload to be accepted. Error: " + ipme.getErrorMessage()); } catch (Exception e) { handleCommonErrors(e); } } private static void handleCommonErrors(Exception exception) { try { throw exception; } catch (InternalServerErrorException isee) { System.out.println("Internal Server Error, generally safe to retry with exponential back-off. Error: " + isee.getErrorMessage()); } catch (RequestLimitExceededException rlee) { System.out.println("Throughput exceeds the current throughput limit for your account, increase account level throughput before " + "retrying. Error: " + rlee.getErrorMessage()); } catch (ProvisionedThroughputExceededException ptee) { System.out.println("Request rate is too high. If you're using a custom retry strategy make sure to retry with exponential back-off. " + "Otherwise consider reducing frequency of requests or increasing provisioned capacity for your table or secondary index. Error: " + ptee.getErrorMessage()); } catch (ResourceNotFoundException rnfe) { System.out.println("One of the tables was not found, verify table exists before retrying. Error: " + rnfe.getErrorMessage()); } catch (AmazonServiceException ase) { System.out.println("An AmazonServiceException occurred, indicates that the request was correctly transmitted to the DynamoDB " + "service, but for some reason, the service was not able to process it, and returned an error response instead. Investigate and " + "configure retry strategy. Error type: " + ase.getErrorType() + ". Error message: " + ase.getErrorMessage()); } catch (AmazonClientException ace) { System.out.println("An AmazonClientException occurred, indicates that the client was unable to get a response from DynamoDB " + "service, or the client was unable to parse the response from the service. Investigate and configure retry strategy. "+ "Error: " + ace.getMessage()); } catch (Exception e) { System.out.println("An exception occurred, investigate and configure retry strategy. Error: " + e.getMessage()); } } }

以下示例显示了 DynamoDB 读取具有 WHERE 子句中所指定不同条件的项目时的不同返回值。

Amazon CLI
  1. 将以下 JSON 代码保存到名为 partiql.json 的文件

    [ // Item exists and projected attribute exists { "Statement": "SELECT * FROM "Music" WHERE Artist='No One You Know' and SongTitle='Call Me Today'" }, // Item exists but projected attributes do not exist { "Statement": "SELECT non_existent_projected_attribute FROM "Music" WHERE Artist='No One You Know' and SongTitle='Call Me Today'" }, // Item does not exist { "Statement": "SELECT * FROM "Music" WHERE Artist='No One I Know' and SongTitle='Call You Today'" } ]
  2. 命令提示符中的以下命令。

    aws dynamodb execute-transaction --transact-statements file://partiql.json
  3. 如果成功,将返回以下响应。

    { "Responses": [ // Item exists and projected attribute exists { "Item": { "Artist":{ "S": "No One You Know" }, "SongTitle":{ "S": "Call Me Today" } } }, // Item exists but projected attributes do not exist { "Item": {} }, // Item does not exist {} ] }