

# PartiQL – 用于 Amazon DynamoDB 的 SQL 兼容语言
<a name="ql-reference"></a>

Amazon DynamoDB 支持 [PartiQL](https://partiql.org/)（一种 SQL 兼容查询语言），用于在 Amazon DynamoDB 中选择、插入、更新和删除数据。使用 PartiQL，您可以轻松地与 DynamoDB 表进行交互，并使用 AWS 管理控制台、NoSQL Workbench、AWS Command Line Interface 以及用于 PartiQL 的 DynamoDB API 运行临时查询。

PartiQL 操作提供与其他 DynamoDB 数据层面操作相同的可用性、延迟和性能。

以下部分介绍 PartiQL 的 DynamoDB 实现。

**Topics**
+ [什么是 PartiQL？](#ql-reference.what-is)
+ [Amazon DynamoDB 中的 PartiQL](#ql-reference.what-is)
+ [开始使用](ql-gettingstarted.md)
+ [数据类型](ql-reference.data-types.md)
+ [语句](ql-reference.statements.md)
+ [函数](ql-functions.md)
+ [运算符](ql-operators.md)
+ [事务](ql-reference.multiplestatements.transactions.md)
+ [分批操作](ql-reference.multiplestatements.batching.md)
+ [IAM 策略](ql-iam.md)

## 什么是 PartiQL？
<a name="ql-reference.what-is"></a>

*PartiQL* 在包含结构化数据、半结构化数据和嵌套数据的多个数据存储中提供 SQL 兼容的查询访问。它在 Amazon 中广泛使用，现在可作为许多 AWS 服务（包括 DynamoDB）的一部分提供。

有关 PartiQL 规范和核心查询语言的教程，请参阅 [ParameSQL 文档](https://partiql.org/docs.html)。

**注意**  
Amazon DynamoDB 支持 [PartiQL](https://partiql.org/) 查询语言的*子集*。
Amazon DynamoDB 不支持 [Amazon ion](http://amzn.github.io/ion-docs/) 数据格式或 Amazon ion 文字。

## Amazon DynamoDB 中的 PartiQL
<a name="ql-reference.what-is"></a>

要在 DynamoDB 中运行 PartiQL 查询，您可以使用：
+ DynamoDB 控制台
+ NoSQL Workbench
+ AWS Command Line Interface（AWS CLI）
+ DynamoDB API

有关使用这些方法访问 DynamoDB 的信息，请参阅[访问 DynamoDB](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/AccessingDynamoDB.html)。

# PartiQL for DynamoDB 入门
<a name="ql-gettingstarted"></a>

本节介绍如何从 Amazon DynamoDB 控制台、AWS Command Line Interface (AWS CLI) 和 DynamoDB API 使用 PartiQL for DynamoDB。

在以下 DynamoDB 例中，[DynamoDB 入门](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/GettingStartedDynamoDB.html)教程中定义的 DynamoDB 表是一个前提条件。

有关使用 DynamoDB 控制台、AWS Command Line Interface 或 DynamoDB API 访问 DynamoDB 的信息，请参阅[访问 DynamoDB](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/AccessingDynamoDB.html)。

要[下载](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/workbench.settingup.html)并使用 [NoSQL Workbench](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/workbench.html) 生成 [PartiQL for DynamoDB](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/ql-reference.html) 语句，请选择 NoSQL Workbench for DynamoDB [操作生成器](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/workbench.querybuilder.operationbuilder.html)右上角的 **PartiQL operations**（PartiQL 操作）。

------
#### [ Console ]

![\[PartiQL 编辑器界面，显示对 Music 表运行查询操作的结果。\]](http://docs.aws.amazon.com/zh_cn/amazondynamodb/latest/developerguide/images/partiqlgettingstarted.png)


1. 登录 AWS 管理控制台，打开 DynamoDB 控制台：[https://console.aws.amazon.com/dynamodb/](https://console.aws.amazon.com/dynamodb/)。

1. 在控制台左侧的导航窗格中，选择 **PartiQL editor (PartiQL 编辑器)**。

1. 选择 **Music** 表。

1. 选择 **Query table (查询表)**。此操作生成不会导致完整表扫描的查询。

1. 将 `partitionKeyValue` 替换为字符串值 `Acme Band`。将 `sortKeyValue` 替换为字符串值 `Happy Day`。

1. 选择 **Run (运行)** 按钮。

1. 选择 **Table view (表视图)** 或 **JSON view (JSON 视图)** 按钮，查看查询结果。

------
#### [ NoSQL workbench ]

![\[NoSQL Workbench 界面。它显示一条 PartiQL SELECT 语句，您可以对 Music 表运行该语句。\]](http://docs.aws.amazon.com/zh_cn/amazondynamodb/latest/developerguide/images/workbench/partiql.single.png)


1. 选择 **PartiQL statement (PartiQL 语句)**。

1. 输入以下 PartiQL [SELECT 语句](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/ql-reference.select.html) 

   ```
   SELECT *                                         
   FROM Music  
   WHERE Artist=? and SongTitle=?
   ```

1. 指定 `Artist` 和 `SongTitle` 参数值：

   1. 选择 **Optional request parameters (可选请求参数)**。

   1. 选择 **Add new parameters (添加新参数)**。

   1. 选择属性类型 **string** 和值 `Acme Band`。

   1. 重复步骤 b 和 c，然后选择类型 **string** 和值 `PartiQL Rocks`。

1. 如果要生成代码，请选择 **Generate code (生成代码)**。

   从显示的选项卡中选择所需的语言。现在，您便可复制此代码并在应用程序中使用它。

1. 如果要立即执行操作，请选择 **Run (执行)**。

------
#### [ AWS CLI ]

1. 使用 INSERT PartiQL 语句在 `Music` 表中创建项目。

   ```
   aws dynamodb execute-statement --statement "INSERT INTO Music  \
   					    VALUE  \
   					    {'Artist':'Acme Band','SongTitle':'PartiQL Rocks'}"
   ```

1. 使用 SELECT PartiQL 语句从 Music 表中检索项目。

   ```
   aws dynamodb execute-statement --statement "SELECT * FROM Music   \
                                               WHERE Artist='Acme Band' AND SongTitle='PartiQL Rocks'"
   ```

1. 使用 INSERT PartiQL 语句在 `Music` 表中更新项目。

   ```
   aws dynamodb execute-statement --statement "UPDATE Music  \
                                               SET AwardsWon=1  \
                                               SET AwardDetail={'Grammys':[2020, 2018]}  \
                                               WHERE Artist='Acme Band' AND SongTitle='PartiQL Rocks'"
   ```

   为 `Music` 表中的项目添加列表值。

   ```
   aws dynamodb execute-statement --statement "UPDATE Music  \
                                               SET AwardDetail.Grammys =list_append(AwardDetail.Grammys,[2016])  \
                                               WHERE Artist='Acme Band' AND SongTitle='PartiQL Rocks'"
   ```

   为 `Music` 表中的项目移除列表值。

   ```
   aws dynamodb execute-statement --statement "UPDATE Music  \
                                               REMOVE AwardDetail.Grammys[2]  \
                                               WHERE Artist='Acme Band' AND SongTitle='PartiQL Rocks'"
   ```

   为 `Music` 表中的项目添加映射成员。

   ```
   aws dynamodb execute-statement --statement "UPDATE Music  \
                                               SET AwardDetail.BillBoard=[2020]  \
                                               WHERE Artist='Acme Band' AND SongTitle='PartiQL Rocks'"
   ```

   为 `Music` 表中的项目添加新字符串集属性。

   ```
   aws dynamodb execute-statement --statement "UPDATE Music  \
                                               SET BandMembers =<<'member1', 'member2'>>  \
                                               WHERE Artist='Acme Band' AND SongTitle='PartiQL Rocks'"
   ```

   为 `Music` 表中的项目更新字符串集属性。

   ```
   aws dynamodb execute-statement --statement "UPDATE Music  \
                                               SET BandMembers =set_add(BandMembers, <<'newmember'>>)  \
                                               WHERE Artist='Acme Band' AND SongTitle='PartiQL Rocks'"
   ```

1. 使用 DELETE PartiQL 语句从 `Music` 表删除项目。

   ```
   aws dynamodb execute-statement --statement "DELETE  FROM Music  \
       WHERE Artist='Acme Band' AND SongTitle='PartiQL Rocks'"
   ```

------
#### [ Java ]

```
import java.util.ArrayList;
import java.util.List;

import com.amazonaws.AmazonClientException;
import com.amazonaws.AmazonServiceException;
import software.amazon.dynamodb.AmazonDynamoDB;
import software.amazon.dynamodb.AmazonDynamoDBClientBuilder;
import software.amazon.dynamodb.model.AttributeValue;
import software.amazon.dynamodb.model.ConditionalCheckFailedException;
import software.amazon.dynamodb.model.ExecuteStatementRequest;
import software.amazon.dynamodb.model.ExecuteStatementResult;
import software.amazon.dynamodb.model.InternalServerErrorException;
import software.amazon.dynamodb.model.ItemCollectionSizeLimitExceededException;
import software.amazon.dynamodb.model.ProvisionedThroughputExceededException;
import software.amazon.dynamodb.model.RequestLimitExceededException;
import software.amazon.dynamodb.model.ResourceNotFoundException;
import software.amazon.dynamodb.model.TransactionConflictException;

public class DynamoDBPartiQGettingStarted {

    public static void main(String[] args) {
        // Create the DynamoDB Client with the region you want
        AmazonDynamoDB dynamoDB = createDynamoDbClient("us-west-1");

        try {
            // Create ExecuteStatementRequest
            ExecuteStatementRequest executeStatementRequest = new ExecuteStatementRequest();
            List<AttributeValue> parameters= getPartiQLParameters();

            //Create an item in the Music table using the INSERT PartiQL statement
            processResults(executeStatementRequest(dynamoDB, "INSERT INTO Music value {'Artist':?,'SongTitle':?}", parameters));

            //Retrieve an item from the Music table using the SELECT PartiQL statement.
            processResults(executeStatementRequest(dynamoDB, "SELECT * FROM Music  where Artist=? and SongTitle=?", parameters));

            //Update an item in the Music table using the UPDATE PartiQL statement.
            processResults(executeStatementRequest(dynamoDB, "UPDATE Music SET AwardsWon=1 SET AwardDetail={'Grammys':[2020, 2018]}  where Artist=? and SongTitle=?", parameters));

            //Add a list value for an item in the Music table.
            processResults(executeStatementRequest(dynamoDB, "UPDATE Music SET AwardDetail.Grammys =list_append(AwardDetail.Grammys,[2016])  where Artist=? and SongTitle=?", parameters));

            //Remove a list value for an item in the Music table.
            processResults(executeStatementRequest(dynamoDB, "UPDATE Music REMOVE AwardDetail.Grammys[2]   where Artist=? and SongTitle=?", parameters));

            //Add a new map member for an item in the Music table.
            processResults(executeStatementRequest(dynamoDB, "UPDATE Music set AwardDetail.BillBoard=[2020] where Artist=? and SongTitle=?", parameters));

            //Add a new string set attribute for an item in the Music table.
            processResults(executeStatementRequest(dynamoDB, "UPDATE Music SET BandMembers =<<'member1', 'member2'>> where Artist=? and SongTitle=?", parameters));

            //update a string set attribute for an item in the Music table.
            processResults(executeStatementRequest(dynamoDB, "UPDATE Music SET BandMembers =set_add(BandMembers, <<'newmember'>>) where Artist=? and SongTitle=?", parameters));

            //Retrieve an item from the Music table using the SELECT PartiQL statement.
            processResults(executeStatementRequest(dynamoDB, "SELECT * FROM Music  where Artist=? and SongTitle=?", parameters));

            //delete an item from the Music Table
            processResults(executeStatementRequest(dynamoDB, "DELETE  FROM Music  where Artist=? and SongTitle=?", parameters));
        } catch (Exception e) {
            handleExecuteStatementErrors(e);
        }
    }

    private static AmazonDynamoDB createDynamoDbClient(String region) {
        return AmazonDynamoDBClientBuilder.standard().withRegion(region).build();
    }

    private static List<AttributeValue> getPartiQLParameters() {
        List<AttributeValue> parameters = new ArrayList<AttributeValue>();
        parameters.add(new AttributeValue("Acme Band"));
        parameters.add(new AttributeValue("PartiQL Rocks"));
        return parameters;
    }

    private static ExecuteStatementResult executeStatementRequest(AmazonDynamoDB client, String statement, List<AttributeValue> parameters ) {
        ExecuteStatementRequest request = new ExecuteStatementRequest();
        request.setStatement(statement);
        request.setParameters(parameters);
        return client.executeStatement(request);
    }

    private static void processResults(ExecuteStatementResult executeStatementResult) {
        System.out.println("ExecuteStatement successful: "+ executeStatementResult.toString());

    }

    // Handles errors during ExecuteStatement execution. Use recommendations in error messages below to add error handling specific to
    // your application use-case.
    private static void handleExecuteStatementErrors(Exception exception) {
        try {
            throw exception;
        } catch (ConditionalCheckFailedException ccfe) {
            System.out.println("Condition check specified in the operation failed, review and update the condition " +
                                       "check before retrying. Error: " + ccfe.getErrorMessage());
        } catch (TransactionConflictException tce) {
            System.out.println("Operation was rejected because there is an ongoing transaction for the item, generally " +
                                       "safe to retry with exponential back-off. Error: " + tce.getErrorMessage());
        } catch (ItemCollectionSizeLimitExceededException icslee) {
            System.out.println("An item collection is too large, you\'re using Local Secondary Index and exceeded " +
                                       "size limit of items per partition key. Consider using Global Secondary Index instead. Error: " + icslee.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());
        }
    }

}
```

------

## 使用参数化语句
<a name="ql-gettingstarted.parameterized"></a>

您可以使用问号（`?`）占位符并在 `Parameters` 字段中单独提供值，而不是将值直接嵌入到 PartiQL 语句字符串中。每个 `?` 值都按提供的顺序替换为相应的参数值。

使用参数化语句是一种最佳实践，因为这可以将语句结构与数据值分开，从而使语句更易于读懂和重复使用。这还可以避免在语句字符串中手动格式化和转义属性值的需求。

`ExecuteStatement`、`BatchExecuteStatement` 和 `ExecuteTransaction` 操作支持参数化语句。

以下示例使用分区键和排序键的参数化值从 `Music` 表中检索项目。

------
#### [ AWS CLI parameterized ]

```
aws dynamodb execute-statement \
    --statement "SELECT * FROM \"Music\" WHERE Artist=? AND SongTitle=?" \
    --parameters '[{"S": "Acme Band"}, {"S": "PartiQL Rocks"}]'
```

------
#### [ Java parameterized ]

```
List<AttributeValue> parameters = new ArrayList<>();
parameters.add(new AttributeValue("Acme Band"));
parameters.add(new AttributeValue("PartiQL Rocks"));

ExecuteStatementRequest request = new ExecuteStatementRequest()
    .withStatement("SELECT * FROM Music WHERE Artist=? AND SongTitle=?")
    .withParameters(parameters);

ExecuteStatementResult result = dynamoDB.executeStatement(request);
```

------
#### [ Python parameterized ]

```
response = dynamodb_client.execute_statement(
    Statement="SELECT * FROM Music WHERE Artist=? AND SongTitle=?",
    Parameters=[
        {'S': 'Acme Band'},
        {'S': 'PartiQL Rocks'}
    ]
)
```

------

**注意**  
前面入门部分中的 Java 示例自始至终都在使用参数化语句。`getPartiQLParameters()` 方法构建参数列表，每条语句都使用 `?` 占位符而不是内联值。

# DynamoDB 的 PartiQL 数据类型
<a name="ql-reference.data-types"></a>

下表列出可用于 PartiQL for DynamoDB 的数据类型。

[\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/zh_cn/amazondynamodb/latest/developerguide/ql-reference.data-types.html)

## 示例
<a name="ql-reference.data-types"></a>

以下语句演示如何插入以下数据类型：`String`、`Number`、`Map`、`List`、`Number Set` 和 `String Set`。

```
INSERT INTO TypesTable value {'primarykey':'1', 
'NumberType':1,
'MapType' : {'entryname1': 'value', 'entryname2': 4}, 
'ListType': [1,'stringval'], 
'NumberSetType':<<1,34,32,4.5>>, 
'StringSetType':<<'stringval','stringval2'>>
}
```

以下语句演示了如何将新元素插入到 `Map`、`List`、`Number Set` 和 `String Set`类型并更改 `Number` 类型的值。

```
UPDATE TypesTable 
SET NumberType=NumberType + 100 
SET MapType.NewMapEntry=[2020, 'stringvalue', 2.4]
SET ListType = LIST_APPEND(ListType, [4, <<'string1', 'string2'>>])
SET NumberSetType= SET_ADD(NumberSetType, <<345, 48.4>>)
SET StringSetType = SET_ADD(StringSetType, <<'stringsetvalue1', 'stringsetvalue2'>>)
WHERE primarykey='1'
```

以下语句演示如何从 `Map`、`List`、`Number Set` 和 `String Set` 类型移除元素，并更改 `Number` 类型的值。

```
UPDATE TypesTable 
SET NumberType=NumberType - 1
REMOVE ListType[1]
REMOVE MapType.NewMapEntry
SET NumberSetType = SET_DELETE( NumberSetType, <<345>>)
SET StringSetType = SET_DELETE( StringSetType, <<'stringsetvalue1'>>)
WHERE primarykey='1'
```

有关更多信息，请参阅 [DynamoDB 数据类型](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/HowItWorks.NamingRulesDataTypes.html#HowItWorks.DataTypes)。

# PartiQL for DynamoDB 语句
<a name="ql-reference.statements"></a>

Amazon DynamoDB 支持以下 PartiQL 语句。

**注意**  
DynamoDB 不支持所有 PartiQL 语句。  
此参考提供可以使用 AWS CLI 或 API 手动运行的 PartiQL 语句的基本语法和用法示例。

*数据操作语言* (DML) 是一组用于管理 DynamoDB 表中的数据的 PartiQL 语句。可以使用 DML 语句在表中添加、修改或删除数据。

支持以下 DML 和查询语言语句：
+ [PartiQL for DynamoDB 的 Select 语句](ql-reference.select.md)
+ [PartiQL for DynamoDB Update 语句](ql-reference.update.md)
+ [PartiQL for DynamoDB Insert 语句](ql-reference.insert.md)
+ [PartiQL for DynamoDB Delete 语句](ql-reference.delete.md)

PartiQL for DynamoDB 还支持 [使用 PartiQL for DynamoDB 执行事务](ql-reference.multiplestatements.transactions.md) 和 [对 PartiQL for DynamoDB 运行批处理操作](ql-reference.multiplestatements.batching.md)。

# PartiQL for DynamoDB 的 Select 语句
<a name="ql-reference.select"></a>

使用 `SELECT` 语句从 Amazon DynamoDB 的表检索数据。

如果 WHERE 子句中未提供带有分区键的相等或 IN 条件，使用 `SELECT` 语句会导致全表扫描。扫描操作会检查每个项目的请求值，并且可以在单个操作中使用大型表或索引的预置吞吐量。

如果您想避免在 PartiQL 中进行全表扫描，您可以：
+ 创作您的 `SELECT` 语句不会导致全表扫描，方法是确保您的 [WHERE 子句条件](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/ql-reference.select.html#ql-reference.select.parameters)相应地配置。
+ 使用《DynamoDB 开发人员指南》[示例：允许 Select 语句并拒绝 PartiQL for DynamoDB 的完整表扫描语句](ql-iam.md#access-policy-ql-iam-example6)中指定的 IAM 策略禁用全表扫描。

有关更多信息，请参阅《DynamoDB 开发人员指南》中的[查询和扫描数据的最佳实践](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/bp-query-scan.html)。

**Topics**
+ [语法](#ql-reference.select.syntax)
+ [参数](#ql-reference.select.parameters)
+ [示例](#ql-reference.select.examples)

## 语法
<a name="ql-reference.select.syntax"></a>

```
SELECT expression  [, ...] 
FROM table[.index]
[ WHERE condition ] [ [ORDER BY key [DESC|ASC] , ...]
```

## 参数
<a name="ql-reference.select.parameters"></a>

***expression***  
（必需）从 `*` 通配符形成的投影，或者结果集的一个或多个属性名称或文档路径的投影列表。表达式可以包括对 [将 PartiQL 函数和 DynamoDB 结合使用](ql-functions.md) 或通过 [用于 DynamoDB 的 PartiQL 算术、比较和逻辑运算符](ql-operators.md) 修改的字段的调用。

***table***  
（必需）要查询的表名。

***index***  
（可选）要查询的索引的名称。  
查询索引时，必须在表名和索引名称中添加双引号。  

```
SELECT * 
FROM "TableName"."IndexName"
```

***条件***  
（可选）查询的选择条件。  
为了确保 `SELECT` 语句不会导致全表扫描，`WHERE` 子句条件必须指定分区键。使用相等或 IN 运算符。  
例如，如果 `Orders` 表有 `OrderID` 分区键和其他非键属性，包括 `Address`，则以下语句不会导致完整表扫描：  

```
SELECT * 
FROM "Orders" 
WHERE OrderID = 100

SELECT * 
FROM "Orders" 
WHERE OrderID = 100 and Address='some address'

SELECT * 
FROM "Orders" 
WHERE OrderID = 100 or OrderID = 200

SELECT * 
FROM "Orders" 
WHERE OrderID IN [100, 300, 234]
```
以下 `SELECT` 语句将导致完整表扫描：  

```
SELECT * 
FROM "Orders" 
WHERE OrderID > 1

SELECT * 
FROM "Orders" 
WHERE Address='some address'

SELECT * 
FROM "Orders" 
WHERE OrderID = 100 OR Address='some address'
```

***键***  
（可选）用于对返回结果进行排序的哈希键或排序键。默认顺序为升序 (`ASC`) 指定 `DESC` 如果您希望按降序重新调整结果。

**注意**  
如果省略 `WHERE` 子句，则检索表中的所有项目。

## 示例
<a name="ql-reference.select.examples"></a>

以下查询指定分区键 `OrderID`，并使用相等运算符，返回 `Orders` 表中的一个项目（如果存在）。

```
SELECT OrderID, Total
FROM "Orders"
WHERE OrderID = 1
```

以下查询使用 OR 运算符返回 `Orders` 表中具有特定分区键 `OrderID` 的所有项目。

```
SELECT OrderID, Total
FROM "Orders"
WHERE OrderID = 1 OR OrderID = 2
```

以下查询使用 IN 运算符返回 `Orders` 表中具有特定分区键 `OrderID` 的所有项目。返回的结果基于 `OrderID` 密钥属性值按降序排列。

```
SELECT OrderID, Total
FROM "Orders"
WHERE OrderID IN [1, 2, 3] ORDER BY OrderID DESC
```

以下查询显示一个全表扫描，返回 `Orders` 表中 `Total` 大于 500，`Total` 是非键属性的所有项目。

```
SELECT OrderID, Total 
FROM "Orders"
WHERE Total > 500
```

以下查询显示一个全表扫描，使用 IN 运算符和非键属性 `Total` 返回 `Orders` 表特定 `Total` 订单范围内的所有项目。

```
SELECT OrderID, Total 
FROM "Orders"
WHERE Total IN [500, 600]
```

以下查询显示一个全表扫描，使用 BETWEEN 运算符和非键属性 `Total` 返回 `Orders` 表特定 `Total` 订单范围内的所有项目。

```
SELECT OrderID, Total 
FROM "Orders" 
WHERE Total BETWEEN 500 AND 600
```

下面的查询在 WHERE 子句条件中指定分区键 `CustomerID` 和排序键 `MovieID`，在 SELECT 子句中使用完整文档路径，返回使用 firestick 设备观察的首个日期。

```
SELECT Devices.FireStick.DateWatched[0] 
FROM WatchList 
WHERE CustomerID= 'C1' AND MovieID= 'M1'
```

以下查询显示了一个完整表扫描，此扫描在 WHERE 子句条件中使用文档路径，返回 12/24/19 之后首次使用 firestick 设备的项目列表。

```
SELECT Devices 
FROM WatchList 
WHERE Devices.FireStick.DateWatched[0] >= '12/24/19'
```

# PartiQL for DynamoDB Update 语句
<a name="ql-reference.update"></a>

使用 `UPDATE` 语句来修改 Amazon DynamoDB 表中某个项目中一个或多个属性的值。

**注意**  
一次只能更新一个项目；不能发出单个 DynamoDB PartiQL 语句更新多个项目。有关更新多个项目的信息，请参阅 [使用 PartiQL for DynamoDB 执行事务](ql-reference.multiplestatements.transactions.md) 或 [对 PartiQL for DynamoDB 运行批处理操作](ql-reference.multiplestatements.batching.md)。

**Topics**
+ [语法](#ql-reference.update.syntax)
+ [参数](#ql-reference.update.parameters)
+ [返回值](#ql-reference.update.return)
+ [示例](#ql-reference.update.examples)

## 语法
<a name="ql-reference.update.syntax"></a>

```
UPDATE  table  
[SET | REMOVE]  path  [=  data] […]
WHERE condition [RETURNING returnvalues]
<returnvalues>  ::= [ALL OLD | MODIFIED OLD | ALL NEW | MODIFIED NEW] *
```

## 参数
<a name="ql-reference.update.parameters"></a>

***表*\$1**  
（必需）包含要修改的数据的表。

***path***  
（必需）要创建或修改的属性名称或文档路径。

***data***  
（必需）属性值或操作的结果。  
要与 SET 一起使用的支持操作：  
+ LIST\$1APPEND：向列表类型添加一个值。
+ SET\$1ADD：将值添加到数字或字符串集。
+ SET\$1DELETE：从数字或字符串集中删除值。

***条件***  
（必需）要修改的项目的选择条件。此条件必须解析为单个主键值。

***returnvalues***  
（可选）如果希望获取更新之前或之后显示的项目属性，使用 `returnvalues`。有效值为：  
+ `ALL OLD *` - 返回更新操作前项目的所有属性。
+ `MODIFIED OLD *` - 仅返回更新操作前已更新的属性。
+ `ALL NEW *` - 返回更新操作后显示的项目的所有属性。
+ `MODIFIED NEW *` - 仅返回 `UpdateItem` 操作后已更新的属性。

## 返回值
<a name="ql-reference.update.return"></a>

此语句不返回值，除非指定 `returnvalues` 参数。

**注意**  
如果对于 DynamoDB 表中的任何项目，UPDATE 语句的 WHERE 子句计算结果不为 true，则返回 `ConditionalCheckFailedException`。

## 示例
<a name="ql-reference.update.examples"></a>

更新现有项目的属性值。如果属性不存在，则创建该属性。

下面的查询添加一个 number 类型参数 (`AwardsWon`) 和一个 map 类型参数 (`AwardDetail`)，更新 `"Music"` 表的项目。

```
UPDATE "Music" 
SET AwardsWon=1 
SET AwardDetail={'Grammys':[2020, 2018]}  
WHERE Artist='Acme Band' AND SongTitle='PartiQL Rocks'
```

您可以添加 `RETURNING ALL OLD *` 以返回在 `Update` 操作之前显示的属性。

```
UPDATE "Music" 
SET AwardsWon=1 
SET AwardDetail={'Grammys':[2020, 2018]}  
WHERE Artist='Acme Band' AND SongTitle='PartiQL Rocks'
RETURNING ALL OLD *
```

这将返回以下内容：

```
{
    "Items": [
        {
            "Artist": {
                "S": "Acme Band"
            },
            "SongTitle": {
                "S": "PartiQL Rocks"
            }
        }
    ]
}
```

您可以添加 `RETURNING ALL NEW *` 以返回在 `Update` 操作之后显示的属性。

```
UPDATE "Music" 
SET AwardsWon=1 
SET AwardDetail={'Grammys':[2020, 2018]}  
WHERE Artist='Acme Band' AND SongTitle='PartiQL Rocks'
RETURNING ALL NEW *
```

这将返回以下内容：

```
{
    "Items": [
        {
            "AwardDetail": {
                "M": {
                    "Grammys": {
                        "L": [
                            {
                                "N": "2020"
                            },
                            {
                                "N": "2018"
                            }
                        ]
                    }
                }
            },
            "AwardsWon": {
                "N": "1"
            }
        }
    ]
}
```

以下查询通过附加到列表 `AwardDetail.Grammys`，更新 `"Music"` 表中的项目。

```
UPDATE "Music" 
SET AwardDetail.Grammys =list_append(AwardDetail.Grammys,[2016])  
WHERE Artist='Acme Band' AND SongTitle='PartiQL Rocks'
```

以下查询通过从列表 `AwardDetail.Grammys` 移除，更新 `"Music"` 表中的项目。

```
UPDATE "Music" 
REMOVE AwardDetail.Grammys[2]   
WHERE Artist='Acme Band' AND SongTitle='PartiQL Rocks'
```

以下查询通过将 `BillBoard` 添加到映射 `AwardDetail`，更新 `"Music"` 表中的项目。

```
UPDATE "Music" 
SET AwardDetail.BillBoard=[2020] 
WHERE Artist='Acme Band' AND SongTitle='PartiQL Rocks'
```

以下查询添加字符串集属性 `BandMembers`，更新 `"Music"` 表中的项目。

```
UPDATE "Music" 
SET BandMembers =<<'member1', 'member2'>> 
WHERE Artist='Acme Band' AND SongTitle='PartiQL Rocks'
```

以下查询将 `newbandmember` 添加到字符串集 `BandMembers`，更新 `"Music"` 表中的项目。

```
UPDATE "Music" 
SET BandMembers =set_add(BandMembers, <<'newbandmember'>>) 
WHERE Artist='Acme Band' AND SongTitle='PartiQL Rocks'
```

# PartiQL for DynamoDB Delete 语句
<a name="ql-reference.delete"></a>

使用 `DELETE` 语句从 Amazon DynamoDB 表中删除现有项目。

**注意**  
一次只能删除一个项目。不能发出单个 DynamoDB PartiQL 语句，删除多个项目。有关删除多个项目的信息，请参阅 [使用 PartiQL for DynamoDB 执行事务](ql-reference.multiplestatements.transactions.md) 或 [对 PartiQL for DynamoDB 运行批处理操作](ql-reference.multiplestatements.batching.md)。

**Topics**
+ [语法](#ql-reference.delete.syntax)
+ [参数](#ql-reference.delete.parameters)
+ [返回值](#ql-reference.delete.return)
+ [示例](#ql-reference.delete.examples)

## 语法
<a name="ql-reference.delete.syntax"></a>

```
DELETE FROM table 
 WHERE condition [RETURNING returnvalues]
 <returnvalues>  ::= ALL OLD *
```

## 参数
<a name="ql-reference.delete.parameters"></a>

***表*\$1**  
（必需）包含要删除的项目的 DynamoDB 表。

***条件***  
（必需）要删除的项目的选择条件；此条件必须解析为单个主键值。

***returnvalues***  
（可选）如果要获得删除前的项目属性，请使用 `returnvalues`。有效值为：  
+ `ALL OLD *` - 返回旧项目的内容。

## 返回值
<a name="ql-reference.delete.return"></a>

此语句不返回值，除非指定 `returnvalues` 参数。

**注意**  
如果 DynamoDB 表中没有任何与发出 DELETE 的项目的主键相同的项目，则返回 SUCCESS 并删除 0 个项目。如果表具有具有相同主键的项目，但 DELETE 语句的 WHERE 子句中的条件计算结果为 false，则返回 `ConditionalCheckFailedException`。

## 示例
<a name="ql-reference.delete.examples"></a>

以下查询删除 `"Music"` 表中的一个项目。

```
DELETE FROM "Music" WHERE "Artist" = 'Acme Band' AND "SongTitle" = 'PartiQL Rocks'
```

您可以添加参数 `RETURNING ALL OLD *` 以返回已删除的数据。

```
DELETE FROM "Music" WHERE "Artist" = 'Acme Band' AND "SongTitle" = 'PartiQL Rocks' RETURNING ALL OLD *
```

`Delete` 语句现在返回以下内容：

```
{
    "Items": [
        {
            "Artist": {
                "S": "Acme Band"
            },
            "SongTitle": {
                "S": "PartiQL Rocks"
            }
        }
    ]
}
```

# PartiQL for DynamoDB Insert 语句
<a name="ql-reference.insert"></a>

使用 `INSERT` 语句向 Amazon DynamoDB 的表添加项目。

**注意**  
一次只能插入一个项目；不能发出单个 DynamoDB PartiQL 语句插入多个项目。有关插入多个项目的信息，请参阅 [使用 PartiQL for DynamoDB 执行事务](ql-reference.multiplestatements.transactions.md) 或 [对 PartiQL for DynamoDB 运行批处理操作](ql-reference.multiplestatements.batching.md)。

**Topics**
+ [语法](#ql-reference.insert.syntax)
+ [参数](#ql-reference.insert.parameters)
+ [返回值](#ql-reference.insert.return)
+ [示例](#ql-reference.insert.examples)

## 语法
<a name="ql-reference.insert.syntax"></a>

插入单个项目。

```
INSERT INTO table VALUE item
```

## 参数
<a name="ql-reference.insert.parameters"></a>

***表*\$1**  
（必需）要在其中插入数据的表。表必须已经存在。

***item***  
（必需）表示为 [PartiQL tuple](https://partiql.org/docs.html) 的有效 DynamoDB 项目。您必须仅指定*一个*项目，项目中的每个属性名称都区分大小写，并且可以用*单*引号 (`'...'`) 在 PartiQL 中表示。  
字符串值也用*单*引号 (`'...'`) 在 PartiQL 中表示。

## 返回值
<a name="ql-reference.insert.return"></a>

此语句不返回任何值。

**注意**  
如果 DynamoDB 表中已具有与要插入项目的主键相同的项目，则返回 `DuplicateItemException`。

## 示例
<a name="ql-reference.insert.examples"></a>

```
INSERT INTO "Music" value {'Artist' : 'Acme Band','SongTitle' : 'PartiQL Rocks'}
```

# 将 PartiQL 函数和 DynamoDB 结合使用
<a name="ql-functions"></a>

Amazon DynamoDB 中的 PartiQL 支持以下 SQL 标准函数的内置版本。

**注意**  
DynamoDB 当前不支持任何未包含在此列表中的 SQL 函数。

## 聚合函数
<a name="ql-functions.aggregate"></a>
+ [将 SIZE 函数与 PartiQL for Amazon DynamoDB 结合使用](ql-functions.size.md)

## 条件函数
<a name="ql-functions.conditional"></a>
+ [将 EXISTS 函数与 PartiQL for DynamoDB 结合使用](ql-functions.exists.md)
+ [将 ATTRIBUTE\$1TYPE 函数与 PartiQL for DynamoDB 结合使用](ql-functions.attribute_type.md)
+ [将 BEGINS\$1WITH 函数与 PartiQL for DynamoDB 结合使用](ql-functions.beginswith.md)
+ [将 CONTAINS 函数与 PartiQL for DynamoDB 结合使用](ql-functions.contains.md)
+ [将 MISSING 函数与 PartiQL for DynamoDB 结合使用](ql-functions.missing.md)

# 将 EXISTS 函数与 PartiQL for DynamoDB 结合使用
<a name="ql-functions.exists"></a>

您可以使用 EXISTS 来执行与 [TransactWriteItems](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/transaction-apis.html#transaction-apis-txwriteitems) API 的 `ConditionCheck` 相同的功能。EXISTS 函数只能在事务中使用。

给定一个值，如果该值是非空集合则返回 `TRUE`。否则返回 `FALSE`。

**注意**  
此函数只能用于事务操作。

## 语法
<a name="ql-functions.exists.syntax"></a>

```
EXISTS ( statement )
```

## Arguments
<a name="ql-functions.exists.arguments"></a>

*语句*  
（必需）函数计算的 SELECT 语句。  
SELECT 语句必须指定完整主键和另一个条件。

## 返回类型
<a name="ql-functions.exists.return-type"></a>

`bool`

## 示例
<a name="ql-functions.exists.examples"></a>

```
EXISTS(
    SELECT * FROM "Music" 
    WHERE "Artist" = 'Acme Band' AND "SongTitle" = 'PartiQL Rocks')
```

# 将 BEGINS\$1WITH 函数与 PartiQL for DynamoDB 结合使用
<a name="ql-functions.beginswith"></a>

如果指定的属性以特定子字符串开头，则返回 `TRUE`。

## 语法
<a name="ql-functions.beginswith.syntax"></a>

```
begins_with(path, value )
```

## Arguments
<a name="ql-functions.beginswith.arguments"></a>

*path*  
（必需）要使用的属性名称或文档路径。

*值*  
（必需）要搜索的字符串。

## 返回类型
<a name="ql-functions.beginswith.return-type"></a>

`bool`

## 示例
<a name="ql-functions.beginswith.examples"></a>

```
SELECT * FROM "Orders" WHERE "OrderID"=1 AND begins_with("Address", '7834 24th')
```

# 将 MISSING 函数与 PartiQL for DynamoDB 结合使用
<a name="ql-functions.missing"></a>

如果项目不包含指定的属性，则返回 `TRUE`。此函数只能使用相等和不等运算符。

## 语法
<a name="ql-functions.missing.syntax"></a>

```
 attributename IS | IS NOT  MISSING 
```

## Arguments
<a name="ql-functions.missing.arguments"></a>

*attributename*  
（必需）要查找的属性名称。

## 返回类型
<a name="ql-functions.missing.return-type"></a>

`bool`

## 示例
<a name="ql-functions.missing.examples"></a>

```
SELECT * FROM Music WHERE "Awards" is MISSING
```

# 将 ATTRIBUTE\$1TYPE 函数与 PartiQL for DynamoDB 结合使用
<a name="ql-functions.attribute_type"></a>

如果指定路径中的属性为特定数据类型，则返回 `TRUE`。

## 语法
<a name="ql-functions.attribute_type.syntax"></a>

```
attribute_type( attributename, type )
```

## Arguments
<a name="ql-functions.attribute_type.arguments"></a>

*attributename*  
（必需）要使用的属性名称。

*类型*  
（必需）要检查的属性类型。有关有效值的列表，请参阅 DynamoDB [attribute\$1type](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/Expressions.OperatorsAndFunctions.html#Expressions.OperatorsAndFunctions.Functions)。

## 返回类型
<a name="ql-functions.attribute_type.return-type"></a>

`bool`

## 示例
<a name="ql-functions.attribute_type.examples"></a>

```
SELECT * FROM "Music" WHERE attribute_type("Artist", 'S')
```

# 将 CONTAINS 函数与 PartiQL for DynamoDB 结合使用
<a name="ql-functions.contains"></a>

如果路径指定的属性为以下之一，则返回 `TRUE`：
+ 一个包含特定子字符串的字符串。
+ 一个包含集中某个特定元素的集合。

有关更多信息，请参阅 DynamoDB [contains](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/Expressions.OperatorsAndFunctions.html#Expressions.OperatorsAndFunctions.Functions) 函数。

## 语法
<a name="ql-functions.contains.syntax"></a>

```
contains( path, substring )
```

## Arguments
<a name="ql-functions.contains.arguments"></a>

*path*  
（必需）要使用的属性名称或文档路径。

*substring*  
（必需）要检查的属性子字符串或集合成员。有关更多信息，请参阅 DynamoDB [contains](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/Expressions.OperatorsAndFunctions.html#Expressions.OperatorsAndFunctions.Functions) 函数。

## 返回类型
<a name="ql-functions.contains.return-type"></a>

`bool`

## 示例
<a name="ql-functions.contains.examples"></a>

```
SELECT * FROM "Orders" WHERE "OrderID"=1 AND contains("Address", 'Kirkland')
```

# 将 SIZE 函数与 PartiQL for Amazon DynamoDB 结合使用
<a name="ql-functions.size"></a>

返回一个代表属性字节大小的数字。以下是与 size 结合使用的有效数据类型。有关更多信息，请参阅 DynamoDB [size](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/Expressions.OperatorsAndFunctions.html#Expressions.OperatorsAndFunctions.Functions) 函数。

## 语法
<a name="ql-functions.size.syntax"></a>

```
size( path)
```

## Arguments
<a name="ql-functions.size.arguments"></a>

*path*  
（必需）属性名称或文档路径。  
有关受支持的类型，请参阅 DynamoDB [size](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/Expressions.OperatorsAndFunctions.html#Expressions.OperatorsAndFunctions.Functions) 函数。

## 返回类型
<a name="ql-functions.size.return-type"></a>

`int`

## 示例
<a name="ql-functions.size.examples"></a>

```
 SELECT * FROM "Orders" WHERE "OrderID"=1 AND size("Image") >300
```

# 用于 DynamoDB 的 PartiQL 算术、比较和逻辑运算符
<a name="ql-operators"></a>

Amazon DynamoDB 中的 PartiQL 支持以下 [SQL 标准运算符](https://www.w3schools.com/sql/sql_operators.asp)。

**注意**  
DynamoDB 当前不支持任何未包含在此列表中的 SQL 运算符。

## 算术运算符
<a name="ql-operators.arithmetic"></a>


****  

| 运算符 | 说明 | 
| --- | --- | 
| \$1 | 添加 | 
| - | Subtract | 

## 比较运算符
<a name="ql-operators.comparison"></a>


****  

| 运算符 | 说明 | 
| --- | --- | 
| = | 等于 | 
| <> | 不等于 | 
| \$1= | 不等于 | 
| > | Greater than | 
| < | Less than | 
| >= | 大于或等于 | 
| <= | 小于或等于 | 

## 逻辑运算符
<a name="ql-operators.logical"></a>


****  

| 运算符 | 说明 | 
| --- | --- | 
| AND | 如果 AND 分隔的所有条件都为 TRUE，则为 TRUE | 
| BETWEEN |  如果操作数在比较范围内，则为 `TRUE`。 此运算符包括您对其应用的操作数的下限和上限。  | 
| IN | 如果操作数等于表达式列表的其中之一（最大 50 个哈希属性值或最大 100 个非键属性值），则为 `TRUE`。 结果分页返回，每页最多 10 个项目。如果 `IN` 列表包含更多值，则必须使用响应中返回的 `NextToken` 来检索后续页面。 | 
| IS | 如果运算数是给定 PartiQL 数据类型，包括 NULL 或 MISSING，则为 TRUE | 
| NOT | 反转给定布尔表达式的值 | 
| OR | 如果 OR 分隔的任意条件为 TRUE，则为 TRUE | 

有关使用逻辑运算符的更多信息，请参阅[进行比较](Expressions.OperatorsAndFunctions.md#Expressions.OperatorsAndFunctions.Comparators)和[逻辑评估](Expressions.OperatorsAndFunctions.md#Expressions.OperatorsAndFunctions.LogicalEvaluations)。

# 使用 PartiQL for DynamoDB 执行事务
<a name="ql-reference.multiplestatements.transactions"></a>

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

有关 DynamoDB 事务的更多信息，请参阅[使用 DynamoDB 事务管理复杂工作流](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/transactions.html)。

**注意**  
整个事务必须由读取语句或写语句组成。您不能在一个事务中混合使用这两个语句。EXISTS 函数是一个例外。可用于检查项目的特定属性的条件，类似于 [TransactWriteItems](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/transaction-apis.html#transaction-apis-txwriteitems) API 操作中 `ConditionCheck` 的方式。

**Topics**
+ [语法](#ql-reference.multiplestatements.transactions.syntax)
+ [参数](#ql-reference.multiplestatements.transactions.parameters)
+ [返回值](#ql-reference.multiplestatements.transactions.return)
+ [示例](#ql-reference.multiplestatements.transactions.examples)

## 语法
<a name="ql-reference.multiplestatements.transactions.syntax"></a>

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

## 参数
<a name="ql-reference.multiplestatements.transactions.parameters"></a>

***语句***  
（必需）PartiQL for DynamoDB 支持的语句。  
整个事务必须由读取语句或写语句组成。您不能在一个事务中混合使用这两个语句。

***parametertype***  
（可选）DynamoDB 类型，如果在指定 PartiQL 语句时使用了参数。

***parametervalue***  
（可选）如果在指定 PartiQL 语句时使用了参数，则为参数值。

## 返回值
<a name="ql-reference.multiplestatements.transactions.return"></a>

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

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

## 示例
<a name="ql-reference.multiplestatements.transactions.examples"></a>

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

------
#### [ 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'"
       }
   ]
   ```

1. 在命令提示符中运行以下命令。

   ```
   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'"
       }
   ]
   ```

1.  命令提示符中的以下命令。

   ```
   aws dynamodb execute-transaction --transact-statements  file://partiql.json
   ```

1. 如果成功，将返回以下响应。

   ```
   {
       "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
           {}
       ]
   }
   ```

------

# 对 PartiQL for DynamoDB 运行批处理操作
<a name="ql-reference.multiplestatements.batching"></a>

本部分介绍如何使用处理器操作和 PartiQL for DynamoDB。

**注意**  
整个批处理必须由读取语句或写入语句组成；不能在一个批处理中混合使用这两种语句。
`BatchExecuteStatement` 和 `BatchWriteItem` 每批可执行的语句不超过 25 个。
`BatchExecuteStatement` 利用 `BatchGetItem`，后者在单独的语句中获取主键的列表。

**Topics**
+ [语法](#ql-reference.multiplestatements.batching.syntax)
+ [参数](#ql-reference.multiplestatements.batching.parameters)
+ [示例](#ql-reference.multiplestatements.batching.examples)

## 语法
<a name="ql-reference.multiplestatements.batching.syntax"></a>

```
[
  {
    "Statement": "SELECT pk FROM ProblemSet WHERE pk = 'p#9StkWHYTxm7x2AqSXcrfu7' AND sk = 'info'"
  },
  {
    "Statement": "SELECT pk FROM ProblemSet WHERE pk = 'p#isC2ChceGbxHgESc4szoTE' AND sk = 'info'"
  }
]
```

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

## 参数
<a name="ql-reference.multiplestatements.batching.parameters"></a>

***语句***  
（必需）PartiQL for DynamoDB 支持的语句。  
+ 整个批处理必须由读取语句或写入语句组成；不能在一个批处理中混合使用这两种语句。
+ `BatchExecuteStatement` 和 `BatchWriteItem` 每批可执行的语句不超过 25 个。

***parametertype***  
（可选）DynamoDB 类型，如果在指定 PartiQL 语句时使用了参数。

***parametervalue***  
（可选）如果在指定 PartiQL 语句时使用了参数，则为参数值。

## 示例
<a name="ql-reference.multiplestatements.batching.examples"></a>

------
#### [ AWS CLI ]

1. 将以下 json 保存到一个名为 partiql.json 的文件

   ```
   [
      {
   	 "Statement": "INSERT INTO Music VALUE {'Artist':?,'SongTitle':?}",
   	  "Parameters": [{"S": "Acme Band"}, {"S": "Best Song"}]
   	},
   	{
   	 "Statement": "UPDATE Music SET AwardsWon=1, AwardDetail={'Grammys':[2020, 2018]} WHERE Artist='Acme Band' AND SongTitle='PartiQL Rocks'"
       }
   ]
   ```

1. 在命令提示符中运行以下命令。

   ```
   aws dynamodb batch-execute-statement  --statements  file://partiql.json
   ```

------
#### [ Java ]

```
public class DynamoDBPartiqlBatch {

    public static void main(String[] args) {
        // Create the DynamoDB Client with the region you want
        AmazonDynamoDB dynamoDB = createDynamoDbClient("us-west-2");
        
        try {
            // Create BatchExecuteStatementRequest
            BatchExecuteStatementRequest batchExecuteStatementRequest = createBatchExecuteStatementRequest();
            BatchExecuteStatementResult batchExecuteStatementResult = dynamoDB.batchExecuteStatement(batchExecuteStatementRequest);
            System.out.println("BatchExecuteStatement successful.");
            // Handle batchExecuteStatementResult

        } catch (Exception e) {
            handleBatchExecuteStatementErrors(e);
        }
    }

    private static AmazonDynamoDB createDynamoDbClient(String region) {

        return AmazonDynamoDBClientBuilder.standard().withRegion(region).build();
    }

    private static BatchExecuteStatementRequest createBatchExecuteStatementRequest() {
        BatchExecuteStatementRequest request = new BatchExecuteStatementRequest();

        // Create statements
        List<BatchStatementRequest> statements = getPartiQLBatchStatements();

        request.setStatements(statements);
        return request;
    }

    private static List<BatchStatementRequest> getPartiQLBatchStatements() {
        List<BatchStatementRequest> statements = new ArrayList<BatchStatementRequest>();

        statements.add(new BatchStatementRequest()
                               .withStatement("INSERT INTO Music value {'Artist':'Acme Band','SongTitle':'PartiQL Rocks'}"));

        statements.add(new BatchStatementRequest()
                               .withStatement("UPDATE Music set AwardDetail.BillBoard=[2020] where Artist='Acme Band' and SongTitle='PartiQL Rocks'"));

        return statements;
    }

    // Handles errors during BatchExecuteStatement execution. Use recommendations in error messages below to add error handling specific to 
    // your application use-case.
    private static void handleBatchExecuteStatementErrors(Exception exception) {
        try {
            throw exception;
        } catch (Exception e) {
            // There are no API specific errors to handle for BatchExecuteStatement, common DynamoDB API errors are handled below
            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());
        }
    }

}
```

------

# 将 IAM 安全策略与 PartiQL for DynamoDB 结合使用
<a name="ql-iam"></a>

需要以下权限：
+ 若要使用 PartiQL for DynamoDB 读取项目，您必须具有表或索引的 `dynamodb:PartiQLSelect` 权限。
+ 若要使用 PartiQL for DynamoDB 插入项目，您必须具有表或索引的 `dynamodb:PartiQLInsert` 权限。
+ 若要使用 PartiQL for DynamoDB 更新项目，您必须具有表或索引的 `dynamodb:PartiQLUpdate` 权限。
+ 若要使用 PartiQL for DynamoDB 删除项目，您必须具有表或索引的 `dynamodb:PartiQLDelete` 权限。

## 示例：允许表上所有 PartiQL for DynamoDB 语句 (Select/Insert/Update/Delete)
<a name="access-policy-ql-iam-example1"></a>

下面的 IAM policy 授予对表运行所有 PartiQL for DynamoDB 语句的权限。

------
#### [ JSON ]

****  

```
{
   "Version":"2012-10-17",		 	 	 
   "Statement":[
      {
         "Effect":"Allow",
         "Action":[
            "dynamodb:PartiQLInsert",
            "dynamodb:PartiQLUpdate",
            "dynamodb:PartiQLDelete",
            "dynamodb:PartiQLSelect"
         ],
         "Resource":[
            "arn:aws:dynamodb:us-west-2:123456789012:table/Music"
         ]
      }
   ]
}
```

------

## 示例：允许表上的 PartiQL for DynamoDB select 语句
<a name="access-policy-ql-iam-example2"></a>

下面的 IAM policy 授予在特定表运行 `select` 语句的权限。

------
#### [ JSON ]

****  

```
{
   "Version":"2012-10-17",		 	 	 
   "Statement":[
      {
         "Effect":"Allow",
         "Action":[
            "dynamodb:PartiQLSelect"
         ],
         "Resource":[
            "arn:aws:dynamodb:us-west-2:123456789012:table/Music"
         ]
      }
   ]
}
```

------

## 示例：允许在索引上运行 PartiQL for DynamoDB insert 语句
<a name="access-policy-ql-iam-example3"></a>

下面的 IAM policy 授予在特定索引运行 `insert` 语句的权限。

------
#### [ JSON ]

****  

```
{
   "Version":"2012-10-17",		 	 	 
   "Statement":[
      {
         "Effect":"Allow",
         "Action":[
            "dynamodb:PartiQLInsert"
         ],
         "Resource":[
            "arn:aws:dynamodb:us-west-2:123456789012:table/Music/index/index1"
         ]
      }
   ]
}
```

------

## 示例：仅允许表上运行 PartiQL for DynamoDB 语句
<a name="access-policy-ql-iam-example4"></a>

下面的 IAM policy 授予在特定表运行事务语句的权限。

------
#### [ JSON ]

****  

```
{
   "Version":"2012-10-17",		 	 	 
   "Statement":[
      {
         "Effect":"Allow",
         "Action":[
            "dynamodb:PartiQLInsert",
            "dynamodb:PartiQLUpdate",
            "dynamodb:PartiQLDelete",
            "dynamodb:PartiQLSelect"
         ],
         "Resource":[
            "arn:aws:dynamodb:us-west-2:123456789012:table/Music"
         ],
         "Condition":{
            "StringEquals":{
               "dynamodb:EnclosingOperation":[
                  "ExecuteTransaction"
               ]
            }
         }
      }
   ]
}
```

------

## 示例：允许运行 PartiQL for DynamoDB 非事务性读取和写入，阻止表上的 PartiQL 事务性读取和写入事务性语句。
<a name="access-policy-ql-iam-example5"></a>

 下面的 IAM policy 授予运行 PartiQL for DynamoDB 非事务性读取和写入的权限，同时阻止 PartiQL for DynamoDB 事务性读取和写入。

------
#### [ JSON ]

****  

```
{
   "Version":"2012-10-17",		 	 	 
   "Statement":[
      {
         "Effect":"Deny",
         "Action":[
            "dynamodb:PartiQLInsert",
            "dynamodb:PartiQLUpdate",
            "dynamodb:PartiQLDelete",
            "dynamodb:PartiQLSelect"
         ],
         "Resource":[
            "arn:aws:dynamodb:us-west-2:123456789012:table/Music"
         ],
         "Condition":{
            "StringEquals":{
               "dynamodb:EnclosingOperation":[
                  "ExecuteTransaction"
               ]
            }
         }
      },
      {
         "Effect":"Allow",
         "Action":[
            "dynamodb:PartiQLInsert",
            "dynamodb:PartiQLUpdate",
            "dynamodb:PartiQLDelete",
            "dynamodb:PartiQLSelect"
         ],
         "Resource":[
            "arn:aws:dynamodb:us-west-2:123456789012:table/Music"
         ]
      }
   ]
}
```

------

## 示例：允许 Select 语句并拒绝 PartiQL for DynamoDB 的完整表扫描语句
<a name="access-policy-ql-iam-example6"></a>

下面的 IAM policy 授予在特定表运行 `select` 语句的权限，同时阻止会导致完整表扫描的 `select` 语句。

------
#### [ JSON ]

****  

```
{
   "Version":"2012-10-17",		 	 	 
   "Statement":[
      {
         "Effect":"Deny",
         "Action":[
            "dynamodb:PartiQLSelect"
         ],
         "Resource":[
            "arn:aws:dynamodb:us-west-2:123456789012:table/WatchList"
         ],
         "Condition":{
            "Bool":{
               "dynamodb:FullTableScan":[
                  "true"
               ]
            }
         }
      },
      {
         "Effect":"Allow",
         "Action":[
            "dynamodb:PartiQLSelect"
         ],
         "Resource":[
            "arn:aws:dynamodb:us-west-2:123456789012:table/WatchList"
         ]
      }
   ]
}
```

------