

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

# 在 Amazon QLDB 中使用 PartiQL 查询 Ion
<a name="ql-reference.query"></a>

**重要**  
终止支持通知：现有客户将能够使用 Amazon QLDB，直到 2025 年 7 月 31 日终止支持。有关更多详细信息，请参阅[将亚马逊 QLDB 账本迁移到亚马逊 Aurora PostgreSQL](https://aws.amazon.com/blogs/database/migrate-an-amazon-qldb-ledger-to-amazon-aurora-postgresql/)。

当您通过 Amazon QLDB 查询数据时，您以 PartiQL 格式编写语句，但是 QLDB 会以 Amazon Ion 格式返回结果。PartiQL 旨在兼容 SQL，而 Ion 是 JSON 的扩展项。这会导致在查询语句中对数据进行注释的方式与查询结果显示方式在语法上存在差异。

本节介绍使用 QLDB 控制台或 [QLDB 控制台](console_QLDB.md) 或 [QLDB Shell](data-shell.md) 手动运行 PartiQL 语句的基本语法和语义。

**提示**  
当以编程方式运行 PartiQL 查询时，最佳做法是使用参数化语句。可在语句中使用问号（`?`）作为绑定变量占位符，以避免使用这些语法规则。这也更安全和高效。  
若要了解更多信息，请参阅*驱动程序入门*中的以下教程：  
Java: [快速入门教程](driver-quickstart-java.md) \$1 [说明书参考](driver-cookbook-java.md)
.NET: [快速入门教程](driver-quickstart-dotnet.md) \$1 [说明书参考](driver-cookbook-dotnet.md)
Go: [快速入门教程](driver-quickstart-golang.md) \$1 [说明书参考](driver-cookbook-golang.md)
Node.js: [快速入门教程](driver-quickstart-nodejs.md) \$1 [说明书参考](driver-cookbook-nodejs.md)
Python: [快速入门教程](driver-quickstart-python.md) \$1 [说明书参考](driver-cookbook-python.md)

**Topics**
+ [

## 语法和语义
](#ql-reference.query.syntax)
+ [

## 反引号表示法
](#ql-reference.query.backtick)
+ [

## 路径导航
](#ql-reference.query.pathing)
+ [

## 别名
](#ql-reference.query.aliasing)
+ [

## PartiQL 规范
](#ql-reference.query.spec)

## 语法和语义
<a name="ql-reference.query.syntax"></a>

使用 QLDB 控制台或 QLDB Shell 查询 Ion 数据时，以下是 PartiQL 的基本语法和语义：

**区分大小写**  
所有 QLDB 系统对象名称（包括字段名、表名和分类账名称）均区分大小写。

**字符串值**  
在 Ion 中，双引号（`"..."`）表示[字符串](https://amzn.github.io/ion-docs/docs/spec.html#string)。  
在 PartiQL 中，单引号（`'...'`）表示字符串。

**符号和标识符**  
在 Ion 中，单引号（`'...'`）表示[符号](https://amzn.github.io/ion-docs/docs/spec.html#symbol)。Ion 中称为*标识符*的符号子集由未加引号的文本表示。  
在 PartiQL 中，双引号（`"..."`）表示带引号的 PartiQL 标识符，如用作表名的[保留字](ql-reference.reserved.md)。未加引号的文本表示常规 PartiQL 标识符，例如非保留字的表名。

**Ion 文本**  
在 PartiQL 语句中，任何 Ion 文字都可以用反引号（``...``）表示。

**字段名称**  
Ion 字段名称区分大小写。PartiQL 允许您在 DML 语句中通过单引号表示字段名称。这是使用 PartiQL `cast`函数定义符号的简写替代方案。它也比使用反引号表示字面上的 Ion 符号更直观。

### 文本
<a name="ql-reference.query.literals"></a>

PartiQL 查询语言的字面值对应 Ion 数据类型，如下所示：

**标量**  
如果适用，请按照 SQL 语法进行操作，如第 [PartiQL-ion 类型映射](ql-reference.docs.md#ql-reference.docs.types) 节所述。例如：  
+ `5`
+ `'foo'`
+ `null`

**Structs**  
也称为多种格式的元组或对象、以及其他数据模型。  
用大括号（`{...}`）表示，其中`struct`元素用逗号分隔。  
+ `{ 'id' : 3, 'arr': [1, 2] }`

**Lists**  
也被称为数组。  
用方括号（`[...]`）表示，列表元素以逗号分隔。  
+ `[ 1, 'foo' ]`

**数据包**  
PartiQL 中的无序集合。  
用双尖括号（`<<...>>`）表示，数据包元素用逗号隔开。在 QLDB 中，表格可以被视为一个数据包。但是，数据包不能嵌套在表格中的文档中。  
+ `<< 1, 'foo' >>`

### 示例
<a name="ql-reference.query.example"></a>

下面是具有各种 Ion 类型`INSERT`语句的语法示例。

```
INSERT INTO VehicleRegistration VALUE
{
    'VIN' : 'KM8SRDHF6EU074761', --string
    'RegNum' : 1722, --integer
    'State' : 'WA',
    'City' : 'Kent',
    'PendingPenaltyTicketAmount' : 130.75, --decimal
    'Owners' : { --nested struct
        'PrimaryOwner' : { 'PersonId': '294jJ3YUoH1IEEm8GSabOs' },
        'SecondaryOwners' : [ --list of structs
            { 'PersonId' : '1nmeDdLo3AhGswBtyM1eYh' },
            { 'PersonId': 'IN7MvYtUjkp1GMZu0F6CG9' }
        ]
    },
    'ValidFromDate' : `2017-09-14T`, --Ion timestamp literal with day precision
    'ValidToDate' : `2020-06-25T`
}
```

## 反引号表示法
<a name="ql-reference.query.backtick"></a>

PartiQL 完全涵盖所有 Ion 数据类型，因此您无需使用反引号即可编写任何语句。但是在某些情况下，这种 Ion 文字语法可以让您的语句更清晰、更简洁。

例如，要插入带有 Ion 时间戳和符号值的文档，可仅使用纯粹的 PartiQL 语法编写以下语句。

```
INSERT INTO myTable VALUE
{
    'myTimestamp': to_timestamp('2019-09-04T'),
    'mySymbol': cast('foo' as symbol)
}
```

这相当冗长，所以你可改用反引号简化你的语句。

```
INSERT INTO myTable VALUE
{
    'myTimestamp': `2019-09-04T`,
    'mySymbol': `foo`
}
```

您也可以用反引号将整个结构括起，以节省更多的按键次数。

```
INSERT INTO myTable VALUE
`{
    myTimestamp: 2019-09-04T,
    mySymbol: foo
}`
```

**重要**  
在 PartiQL 中，字符串和符号类别不同。这意味着，即使它们有相同的文本，也不相等。例如，以下 PartiQL 表达式计算为不同 Ion 值。  

```
'foo'
```

```
`foo`
```

## 路径导航
<a name="ql-reference.query.pathing"></a>

编写数据操作语言（DML）或查询语句时，您可以使用路径步骤访问嵌套结构中的字段。PartiQL 支持使用点表示法访问父结构的字段名称。以下示例访问父项 `Vehicle`的 `Model` 字段。

```
Vehicle.Model
```

若要访问列表中的特定元素，可以使用方括号运算符表示从零开始的序数。以下示例访问序数为`SecondaryOwners`的`2`元素。换句话说，这是列表的第三元素。

```
SecondaryOwners[2]
```

## 别名
<a name="ql-reference.query.aliasing"></a>

QLDB 支持开放内容与架构。因此，当您访问语句中的特定字段时，确保获得预期结果的最佳方法是使用别名。例如，如果您未指定显式别名，则系统会为您的 `FROM` 源生成一个隐式别名。

```
SELECT VIN FROM Vehicle
--is rewritten to
SELECT Vehicle.VIN FROM Vehicle AS Vehicle
```

但是字段名冲突的结果不可预测。如果文档中的嵌套结构中存在另一个名为`VIN`的字段，则此查询返回的`VIN`值可能会让您感到惊讶。作为最佳实践标准，请改写以下语句。此查询声明 `v` 为 `Vehicle` 表的别名。`AS` 关键字是可选的。

```
SELECT v.VIN FROM Vehicle [ AS ] v
```

当路径进入文档中嵌套集合时，别名特别有用。例如，以下语句声明 `o` 为`VehicleRegistration.Owners`覆盖集合的别名。

```
SELECT o.SecondaryOwners
FROM VehicleRegistration AS r, @r.Owners AS o
```

此处的 `@` 字符在技术上是可选的。但它明确表示你想在里面放置一个`Owners`结构`VehicleRegistration`，而不是一个名为不同的集合`Owners`（如有）。

## PartiQL 规范
<a name="ql-reference.query.spec"></a>

[有关 PartiQL 查询语言的更多信息，请参阅 PartiQL 规范。](https://partiql.org/assets/PartiQL-Specification.pdf)