使用 PartiQL for DynamoDB 执行事务 - Amazon DynamoDB

本文属于机器翻译版本。若本译文内容与英语原文存在差异,则一律以英文原文为准。

使用 PartiQL for DynamoDB 执行事务

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

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

注意

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

语法

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

参数

语句

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

注意

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

parametertype

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

parametervalue

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

返回值

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

注意

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

示例

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

AWS 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 子句中所指定不同条件的项目时的不同返回值。

AWS 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 {} ] }