

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

# Amazon QLDB 中的 SELECT 命令
<a name="ql-reference.select"></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 中，使用`SELECT`命令从一个或多个表中检索数据。QLDB 中的每个 `SELECT` 查询都是在事务中处理的，并且受[事务超时限制](limits.md#limits.fixed)的约束。

结果的顺序不指定，可能因每个`SELECT`查询而异。在 QLDB 中，任何查询都不应该依赖结果顺序。

要了解如何控制对特定表运行此 PartiQL 命令的访问权限，请参阅。[请参阅《Amazon QLDB 开发人员》中的标准权限模式入门](getting-started-standard-mode.md)

**警告**  
当你在没有索引查找的情况下运行查询时，它会调用全表扫描。PartiQL 之所以支持此类查询，是因为其与 SQL 兼容。但是，*切勿*在 QLDB 中对生产用例运行表扫描。表扫描可能会导致大型表出现性能问题，包括并发冲突与事务超时。  
为避免表扫描，必须在索引字段或文档 ID 上使用*相等*运算符（`WHERE indexedField = 123`或`WHERE indexedField IN (456, 789)`）运行带有`WHERE`谓词子句的语句。有关更多信息，请参阅 [优化查询性能](working.optimize.md)。

**Topics**
+ [语法](#ql-reference.select.syntax)
+ [参数](#ql-reference.select.parameters)
+ [联接](#ql-reference.select.joins)
+ [嵌套查询限制](#ql-reference.select.subqueries)
+ [示例](#ql-reference.select.examples)
+ [使用驱动程序以编程方式运行](#ql-reference.select.driver)

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

```
SELECT [ VALUE ] expression [ AS field_alias ] [, expression, ... ]
FROM source [ AS source_alias ] [ AT idx_alias ] [ BY id_alias ] [, source, ... ]
[ WHERE condition ]
```

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

**值**  
表达式的限定符，它使查询返回原始数据类型值，而非将值封装在元组结构中。

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

**正如 *field\$1alias***  
（可选）在最终结果集中使用字段的临时别名。`AS` 关键字是可选的。  
如果您没有为不是简单列名的表达式指定别名，则结果集将对该字段应用默认名称。

**来自 *source***  
要查询的来源。当前支持的唯一来源是表名、表之间的[内部联接](#ql-reference.select.joins)、嵌套`SELECT`查询（以[嵌套查询限制](#ql-reference.select.subqueries)）和表的[历史函数](working.history.md) 调用为准。  
您必须指定至少一个源。必须用逗号分隔多个源。

**正如 *source\$1alias***  
（可选）用户定义的别名，范围涵盖要更新的源。`SELECT`、`WHERE` 语句中所用的源别名必须在 `FROM` 语句中声明。`AS` 关键字是可选的。

**在 *idx\$1alias***  
（可选）用户定义的别名，它绑定至源列表中每个元素的索引（序数）。必须使用 `AT` 关键字在 `FROM` 子句中声明别名。

**由 *id\$1alias***  
（可选）用户定义的别名，它绑定至结果集中每个文档的 `id`元数据字段。必须使用 `BY` 关键字在 `FROM` 子句中声明别名。当您想在查询默认用户视图的同时投影或筛选[文档 ID](working.metadata.md)，这很有用。有关更多信息，请参阅 [通过 BY 子句查询文档 ID](working.metadata.by-clause.md)。

**哪里 *condition***  
查询的选择标准和联接标准（如适用）。

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

## 联接
<a name="ql-reference.select.joins"></a>

目前仅支持内部联接。您可以使用显式 `INNER JOIN` 子句编写内部联接查询，如下所示。在此语法中，`JOIN`必须与`ON`配对，并且`INNER` 关键字是可选的。

```
SELECT expression
FROM table1 AS t1 [ INNER ] JOIN table2 AS t2
ON t1.element = t2.element
```

或者，您可以使用隐式语法编写内部联接，如下所示。

```
SELECT expression
FROM table1 AS t1, table2 AS t2
WHERE t1.element = t2.element
```

## 嵌套查询限制
<a name="ql-reference.select.subqueries"></a>

可以在 `SELECT` 表达式和 `FROM` 源代码中编写嵌套查询（子查询）。主要限制是，只有最外层的查询才能访问全局数据库环境。例如，假设您有一个包含表`VehicleRegistration`和`Person`的分类账。以下嵌套查询无效，因为内部`SELECT`试图访问`Person`。

```
SELECT r.VIN,
    (SELECT p.PersonId FROM Person AS p WHERE p.PersonId = r.Owners.PrimaryOwner.PersonId) AS PrimaryOwner
FROM VehicleRegistration AS r
```

而以下嵌套查询是有效的。

```
SELECT r.VIN, (SELECT o.PrimaryOwner.PersonId FROM @r.Owners AS o) AS PrimaryOwner
FROM VehicleRegistration AS r
```

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

以下查询显示了一个基本的 `SELECT`，其中包含使用`IN`运算符的标准`WHERE`谓词子句。

```
SELECT * FROM Vehicle
WHERE VIN IN ('1N4AL11D75C109151', 'KM8SRDHF6EU074761')
```

下图显示了使用字符串筛选条件的 `SELECT` 光投影。

```
SELECT FirstName, LastName, Address 
FROM Person 
WHERE Address LIKE '%Seattle%'
AND GovId = 'LEWISR261LL'
```

下面显示了用于扁平化嵌套数据的相关子查询。此处的 `@` 字符在技术上是可选的。但它明确表示你想在里面放置一个`Owners`结构`VehicleRegistration`，而不是一个名为不同的集合`Owners`（如有）。有关更多背景信息，请参阅 *处理数据和历史记录* 一章中的[嵌套数据](working.userdata.md#working.userdata.nested)。

```
SELECT 
    r.VIN, 
    o.SecondaryOwners
FROM
    VehicleRegistration AS r, @r.Owners AS o
WHERE
    r.VIN IN ('1N4AL11D75C109151', 'KM8SRDHF6EU074761')
```

下图显示了`SELECT` 列表中投射嵌套数据的子查询和隐式内部联接。

```
SELECT
    v.Make, 
    v.Model, 
    (SELECT VALUE o.PrimaryOwner.PersonId FROM @r.Owners AS o) AS PrimaryOwner
FROM 
    VehicleRegistration AS r, Vehicle AS v
WHERE 
    r.VIN = v.VIN AND r.VIN IN ('1N4AL11D75C109151', 'KM8SRDHF6EU074761')
```

下面显示了一个显式的内部联接。

```
SELECT
    v.Make, 
    v.Model, 
    r.Owners
FROM 
    VehicleRegistration AS r JOIN Vehicle AS v
ON
    r.VIN = v.VIN
WHERE
    r.VIN IN ('1N4AL11D75C109151', 'KM8SRDHF6EU074761')
```

下图显示了使用 `BY` 子句对文档 `id` 元数据字段的投影。

```
SELECT
    r_id,
    r.VIN
FROM
    VehicleRegistration AS r BY r_id
WHERE
    r_id = 'documentId'
```

以下内容分别使用`BY`来联接`DriversLicense`和`Person`表的`id`字段`PersonId`和文档字段。

```
SELECT * FROM DriversLicense AS d INNER JOIN Person AS p BY pid
ON d.PersonId = pid
WHERE pid = 'documentId'
```

以下内容使用子[已提交视图](working.metadata.md#working.metadata.committed)句分别连接`DriversLicense`和`Person`表的`id`字段`PersonId`和文档字段。

```
SELECT * FROM DriversLicense AS d INNER JOIN _ql_committed_Person AS cp
ON d.PersonId = cp.metadata.id
WHERE cp.metadata.id = 'documentId'
```

以下内容返回表 `VehicleRegistration` 中文 档`Owners.SecondaryOwners` 列表中每个人的 `PersonId`和索引（序数）。

```
SELECT s.PersonId, owner_idx
FROM VehicleRegistration AS r, @r.Owners.SecondaryOwners AS s AT owner_idx
WHERE r.VIN = 'KM8SRDHF6EU074761'
```

## 使用驱动程序以编程方式运行
<a name="ql-reference.select.driver"></a>

要了解如何使用 QLDB 驱动程序以编程方式运行此语句，请参阅*驱动程序入门*中的以下教程：
+ 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)