

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

# Amazon QLDB PartiQL 参考
<a name="ql-reference"></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](https://partiql.org/) 查询语言的*子集*。以下主题介绍 PartiQL 的 QLDB 实现。

**注意**  
QLDB 不支持所有 PartiQL 操作。
QLDB 中的所有 PartiQL 语句都受事务限制的约束，如[Amazon QLDB 资源中的限额和限制](limits.md#limits.fixed)中所定义。
此参考提供可以使用 QLDB 控制台 或 QLDB Shell 手动运行的 PartiQL 语句的基本语法和用法示例。有关展示如何使用 QLDB 驱动程序以编程方式运行类似语句的代码示例，请参阅[驱动程序入门](getting-started-driver.md)中的教程。

**Topics**
+ [什么是 PartiQL？](#ql-reference.what-is)
+ [Amazon QLDB 中的 PartiQL](#ql-reference.in-qldb)
+ [关于 QLDB 中 PartiQL 的快速小贴士](#ql-reference.tips)
+ [PartiQL 参考惯例](ql-reference.conventions.md)
+ [数据类型](ql-reference.data-types.md)
+ [QLDB 文档](ql-reference.docs.md)
+ [使用 PartiQL 查询 Ion](ql-reference.query.md)
+ [PartiQL 命令](ql-reference.statements.md)
+ [PartiQL 函数](ql-functions.md)
+ [Partiql 存储进程](ql-stored-procedures.md)
+ [PartiQL 运算符](ql-operators.md)
+ [保留关键字](ql-reference.reserved.md)
+ [Amazon](ion.md)

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

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

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

PartiQL 扩展了 [SQL-92](http://www.contrib.andrew.cmu.edu/~shadow/sql/sql1992.txt)，以支持 Amazon Ion 数据格式的文档。有关 Amazon Ion 的更多信息，请参阅 [Amazon QLDB 中的 Amazon Ion 数据格式参考](ion.md)。

## Amazon QLDB 中的 PartiQL
<a name="ql-reference.in-qldb"></a>

若要 QLDB 中运行 PartiQL 查询，您可以使用以下方法之一：
+ QLD *B 上的 PartiQL 编辑器* AWS 管理控制台 
+ 命令行 QLDB Shell
+  AWS 提供的 QLDB 驱动程序，用于以编程方式运行查询

有关使用这些方法访问 QLDB 的更多信息，请参阅 [访问 Amazon QLDB](accessing.md)。

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

## 关于 QLDB 中 PartiQL 的快速小贴士
<a name="ql-reference.tips"></a>

以下是在 QLDB 中使用 PartiQL 的提示和最佳实践小贴士：
+ **了解并发和事务限制** — `SELECT` 查询等所有语句都应遵守[乐观并发控制（OCC）](concurrency.md)冲突和[事务限制](limits.md#limits.fixed)，包括 30 秒事务暂停。
+ **使用索引** - 使用高基数索引，并运行有针对性的查询来优化语句并避免全表扫描。要了解更多信息，请参阅 [优化查询性能](working.optimize.md)。
+ **使用相等谓词** - 索引查找需要*相等*运算符（`=` 或 `IN`）。不等式运算符（`<`、`>`、`LIKE`、`BETWEEN`）不符合索引查找的条件，因此会生成全表扫描。
+ **仅使用内部联接** - QLDB 仅支持内部联接。根据最佳实践标准，在为要加入的每个表编制索引的字段上进行联接。为联接条件与相等谓词选择高基数索引。

# Amazon QLDB PartiQL 参考惯例
<a name="ql-reference.conventions"></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 参考* 中描述的用于编写 PartiQL 命令、函数和表达式语法的约定。不要将这些约定与 PartiQL 查询语言本身的 [语法和语义](ql-reference.query.md#ql-reference.query.syntax)混淆。

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

# Amazon QLDB 中的数据类型
<a name="ql-reference.data-types"></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 以 [Amazon Ion](ion.md)格式存储文档。Amazon Ion 是一种数据序列化格式（文本形式和二进制编码形式），是 JSON 的超集。下表列出了您可在 QLDB 文档中使用的 Ion 数据类型。

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

请参阅 Amazon GitHub 网站上的 [Ion 规范文档](http://amzn.github.io/ion-docs/docs/spec.html)，了解 Ion core 数据类型的完整列表，以及完整的描述和值格式化细节。

# Amazon QLDB 文档
<a name="ql-reference.docs"></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 将数据记录存储为文档，这些文档只是插入到表中的[Amazon Ion](ion.md) `struct`对象。有关 Ion 规范，请访问 [Amazon Ion GitHub](http://amzn.github.io/ion-docs/docs/spec.html) 网站。

**Topics**
+ [Ion 文档结构](#ql-reference.docs.ion)
+ [PartiQL-ion 类型映射](#ql-reference.docs.types)
+ [文档 ID](#ql-reference.docs.id)

## Ion 文档结构
<a name="ql-reference.docs.ion"></a>

与 JSON 一样的是，QLDB 文档由以下结构中的名称/值对组成。

```
{
  name1: value1,
  name2: value2,
  name3: value3,
  ...
  nameN: valueN
}
```

名称为符号标记，其值不受限制。每个名称/值对都称为一个*字段*。字段的值可以是任何 Ion[数据类型](ql-reference.data-types.md)，包括以下容器类型：嵌套结构、列表和结构列表。

与 JSON 一样的是，`struct`用大括号（`{...}`）表示，`list` 用方括号（`[...]`）表示。以下示例是[Amazon QLDB 控制台入门](getting-started.md)中示例数据的文档，其中包含各种类型的值。

```
{
    VIN: "1N4AL11D75C109151",
    LicensePlateNumber: "LEWISR261LL",
    State: "WA",
    City: "Seattle",
    PendingPenaltyTicketAmount: 90.25,
    ValidFrom: 2017-08-21T,
    ValidTo: 2020-05-11T,
    Owners: {
        PrimaryOwner: { PersonId: "294jJ3YUoH1IEEm8GSabOs" },
        SecondaryOwners: [{ PersonId: "5Ufgdlnj06gF5CWcOIu64s" }]
    }
}
```

**重要**  
在 Ion 中，双引号表示字符串值，未加引号符号表示字段名。但在 PartiQL，单引号表示字符串和字段名。  
这种语法差异允许 PartiQL 查询语言保持 SQL 兼容性，使 Amazon Ion 数据格式保持 JSON 兼容性。有关 QLDB 中 PartiQL 的语法和语义详细信息，请参阅[使用 PartiQL 查询 Ion](ql-reference.query.md)。

## PartiQL-ion 类型映射
<a name="ql-reference.docs.types"></a>

在 QLDB，PartiQL 扩展了 SQL 的类型系统，以覆盖 Ion 数据模型。此映射描述如下：
+ SQL 标量类型包含在 Ion 对应物之中。例如：
  + `CHAR`和`VARCHAR`是映射到 Ion `string` 类型的 Unicode 序列。
  + `NUMBER`映射至 Ion `decimal`类型。
+ Ion 的 `struct`类型等同于 SQL 元组，传统上表示表*行*。
  + 但是，在内容开放且没有架构的情况下，不支持依赖 SQL 元组有序性质的查询（例如`SELECT *`的输出顺序）。
+ 除`NULL`之外，PartiQL 还有一个`MISSING`类型。这是一种专业化`NULL`，表明缺少字段。此类型为必要项，因为 Ion `struct` 字段可能很稀少。

## 文档 ID
<a name="ql-reference.docs.id"></a>

QLDB 会为您插入到表格中的每个*文档分配一个文档 ID*。系统分配的所有标识符 IDs 都是通用唯一标识符 (UUID)，每个标识符都以 Base62 编码的字符串表示（例如）。`3Qv67yjXEwB9SjmvkuG6Cp`有关更多信息，请参阅 [IDs 在亚马逊 QLDB 中独树一帜](working.unique-id.md)。

每个文档*修订版*都由文档 ID 和从零开始的版本号组合作为唯一标识。

文档 ID 和版本字段都包含在文档元数据中，您可以在*提交视图*（系统定义的表格视图）中对其进行查询。有关 QLDB 中的这些视图的更多信息，请参阅[核心概念](ledger-structure.md)。了解有关元数据的更多信息，请参阅 [查询文档元数据](working.metadata.md)。

# 在 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)

# Amazon QLDB 中的 PartiQL 命令
<a name="ql-reference.statements"></a>

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

PartiQL 扩展了 SQL-92 以支持 Amazon Ion 数据格式的文档。Amazon QLDB 支持以下 PartiQL 命令。

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

**注意**  
QLDB 不支持所有 PartiQL 命令。
QLDB 中的所有 PartiQL 语句都受事务限制的约束，如[Amazon QLDB 资源中的限额和限制](limits.md#limits.fixed)中所定义。
本参考资料提供了在 QLDB 控制台或 QLDB Shell 上手动运行的 PartiQL 语句的基本语法和用法示例。有关演示如何使用受支持的编程语言运行类似语句的代码示例，请参阅[驱动程序入门](getting-started-driver.md)中的教程。

## DDL 语句（数据定义语言）
<a name="ql-functions.statements.ddl"></a>

*数据定义语言*（DDL）是一组用于管理数据库对象（如表和索引）的 PartiQL 语句。您可以使用 DDL 创建和删除这些对象。
+ [CREATE INDEX](ql-reference.create-index.md)
+ [CREATE TABLE](ql-reference.create-table.md)
+ [DROP INDEX](ql-reference.drop-index.md)
+ [DROP TABLE](ql-reference.drop-table.md)
+ [取消删除表](ql-reference.undrop-table.md)

## DML（数据操作语言）语句
<a name="ql-functions.statements.dml"></a>

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

支持以下 DML 和查询语言语句：
+ [DELETE](ql-reference.delete.md)
+ [FROM（插入、删除或设置）](ql-reference.from.md)
+ [INSERT](ql-reference.insert.md)
+ [SELECT](ql-reference.select.md)
+ [UPDATE](ql-reference.update.md)

# 在 Amazon QLDB 中创建索引命令
<a name="ql-reference.create-index"></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 中，使用`CREATE INDEX`命令为表中的文档字段创建索引。

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

**重要**  
QLDB 需要索引才能高效查找文档。如果没有索引，QLDB 在读取文档时需进行全表扫描。这可能会导致大型表出现性能问题，包括并发冲突与事务超时。  
为避免表扫描，必须在索引字段或文档 ID 上使用*相等*运算符（`=`或`IN`）运行带有`WHERE`谓词子句的语句。有关更多信息，请参阅 [优化查询性能](working.optimize.md)。

创建索引时应注意以下限制：
+ 只能在单个顶级字段创建索引。不支持复合索引、嵌套索引、唯一索引以及基于函数的索引。
+ 您可以为任何 [Ion 数据类型](ql-reference.data-types.md)创建索引，其中包括 `list` 和 `struct`。但是，无论 Ion 类型如何，您都只能通过整个 Ion 值进行索引查找。例如，使用 `list` 类型作为索引时，不能按列表中的一个项目进行索引查找。
+ 只有使用相等谓词时，查询性能才会得到改善；例如`WHERE indexedField = 123` 或 `WHERE indexedField IN (456, 789)`。

  QLDB 不支持查询谓词不等式。因此，未实施范围过滤扫描。
+ 索引字段名称区分大小写，且最大长度可为 128 个字符。
+ 在 QLDB 中创建索引具有异步特点。非空表上完成索引所需的时间取决于表的大小。有关更多信息，请参阅 [管理索引](working.manage-indexes.md)。

**Topics**
+ [语法](#ql-reference.create-index.syntax)
+ [参数](#ql-reference.create-index.parameters)
+ [返回值](#ql-reference.create-index.return)
+ [示例](#ql-reference.create-index.examples)
+ [使用驱动程序以编程方式运行](#ql-reference.create-index.driver)

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

```
CREATE INDEX ON table_name (field)
```

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

***table\$1name***  
要在其中创建索引的表的名称。表必须已经存在。  
表名称区分大小写。

***field***  
要为其创建索引的文档字段的名称。该字段必须为顶级属性。  
索引字段名称区分大小写，且最大长度可为 128 个字符。  
您可以为任何 [Amazon Ion 数据类型](ql-reference.data-types.md)创建索引，包括 `list` 和 `struct`。但是，无论 Ion 类型如何，您都只能通过整个 Ion 值进行索引查找。例如，使用 `list` 类型作为索引时，不能按列表中的一个项目进行索引查找。

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

`tableId` — 您在其上创建索引的表的唯一 ID。

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

```
CREATE INDEX ON VehicleRegistration (LicensePlateNumber)
```

```
CREATE INDEX ON Vehicle (VIN)
```

## 使用驱动程序以编程方式运行
<a name="ql-reference.create-index.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)

# Amazon QLDB 中的 CREATE TABLE 命令
<a name="ql-reference.create-table"></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 中使用 `CREATE TABLE`命令创建新表。

表名称很简单，没有命名空间。QLDB 支持开放内容且不强制架构，因此在创建表时不需要定义属性或数据类型。

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

**Topics**
+ [语法](#ql-reference.create-table.syntax)
+ [参数](#ql-reference.create-table.parameters)
+ [返回值](#ql-reference.create-table.return)
+ [创建标记表](#ql-reference.create-table.tagging)
+ [示例](#ql-reference.create-table.examples)
+ [使用驱动程序以编程方式运行](#ql-reference.create-table.driver)

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

```
CREATE TABLE table_name [ WITH (aws_tags = `{'key': 'value'}`) ]
```

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

***table\$1name***  
要创建的表的唯一名称。不得存在同名活动表。以下是命名约定：  
+ 只能包含 1-128 个字母数字字符或下划线字符。
+ 必须为首个字样或下划线。
+ 其余字符可能是字母数字字符和下划线的任意组合。
+ 区分大小写。
+ 不能是 QLDB PartiQL 的 [保留字](ql-reference.reserved.md)。

**'*key*': '*value*'**  
（可选）在创建表资源时要附加至表资源的标签。每个标签都定义为键值对，其中键和值均以单引号表示。每个键值对都在用反引号表示的 Amazon Ion 结构中定义。  
*目前，只有 `STANDARD` 权限模式分类账支持在创建时对表格进行标记。*

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

`tableId` - 您创建的表的唯一 ID。

## 创建标记表
<a name="ql-reference.create-table.tagging"></a>

**注意**  
 只有 `STANDARD` 权限模式分类账支持在创建时对表格进行标记。

或者，您可以通过`CREATE TABLE`语句中指定标签来标记表资源。有关标签的更多信息，请参阅 [为 Amazon QLDB 资源贴标签](tagging.md)。下面的示例创建了一个名为 `Vehicle` 的表，带有标签 `environment=production`。

```
CREATE TABLE Vehicle WITH (aws_tags = `{'environment': 'production'}`)
```

在创建时为表添加标签，需要同时访问 `qldb:PartiQLCreateTable` 和 `qldb:TagResource` 操作。要了解有关 QLDB 资源权限的更多信息，请参阅[Amazon MQ 如何与 IAM 协同工作](security_iam_service-with-iam.md)。

通过在创建资源时对其进行标记，无需在创建资源后运行自定义标记脚本。标记表后，您可根据这些标签来控制对表的访问。例如：您只能向具有特定标签的表授予完全访问权限。有关 JSON 策略示例，请参阅[基于表格标签对所有操作的完全访问权限](security_iam_id-based-policy-examples.md#security_iam_id-based-policy-examples-full-tags)。

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

```
CREATE TABLE VehicleRegistration
```

```
CREATE TABLE Vehicle WITH (aws_tags = `{'environment': 'development'}`)
```

```
CREATE TABLE Vehicle WITH (aws_tags = `{'key1': 'value1', 'key2': 'value2'}`)
```

## 使用驱动程序以编程方式运行
<a name="ql-reference.create-table.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)

# Amazon QLDB 中的删除命令
<a name="ql-reference.delete"></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 中，通过创建新的但最终版本的文档，使用`DELETE`命令将表中的活动文档标记为已删除。此最终修订版表示此文档已被删除。此操作会结束文档生命周期，这意味着无法再创建具有相同文档 ID 的文档修订版。

该操作不可逆。您仍然可以使用[历史记录函数](working.history.md#working.history.function)查询已删除文档的修订历史记录。

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

**Topics**
+ [语法](#ql-reference.delete.syntax)
+ [参数](#ql-reference.delete.parameters)
+ [返回值](#ql-reference.delete.return)
+ [示例](#ql-reference.delete.examples)
+ [使用驱动程序以编程方式运行](#ql-reference.delete.driver)

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

```
DELETE FROM table_name [ AS table_alias ] [ BY id_alias ]
[ WHERE condition ]
```

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

***table\$1name***  
包含要删除数据的用户表的名称。仅默认[用户视图](working.userdata.md)支持 DML 语句。每条语句只能在单个表中运行。

**正如 *table\$1alias***  
（可选）用户定义的别名，范围涵盖要从中删除的表。`AS` 关键字是可选的。

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

**哪里 *condition***  
待删除文档的选择条件。

**注意**  
如果省略 `WHERE` 子句，则表中的所有文档都被删除。

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

`documentId` — 您删除的每个文档的唯一 ID。

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

```
DELETE FROM VehicleRegistration AS r
WHERE r.VIN = '1HVBBAANXWH544237'
```

## 使用驱动程序以编程方式运行
<a name="ql-reference.delete.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)

# Amazon QLDB 中的 DROP INDEX 命令
<a name="ql-reference.drop-index"></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 中，使用`DROP INDEX`命令删除表上的索引。

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

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

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

```
DROP INDEX "indexId" ON table_name WITH (purge = true)
```

**注意**  
该子句 `WITH (purge = true)` 是所有 `DROP INDEX` 语句所必需的，并且 `true` 是目前唯一支持的值。  
关键字`purge`区分大小写，并且必须为全小写。

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

**"*indexId*"**  
待索引的唯一 ID，用双引号表示。

**开启 *table\$1name***  
要删除索引的表名称。

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

`tableId` - 您删除其索引的表的唯一 ID。

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

```
DROP INDEX "4tPW3fUhaVhDinRgKRLhGU" ON VehicleRegistration WITH (purge = true)
```

# Amazon QLDB 中的 DROP TABLE 命令
<a name="ql-reference.drop-table"></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 中，使用 `DROP TABLE` 命令停用现有表。您可以使用 [取消删除表](ql-reference.undrop-table.md) 语句将其重新激活。停用或重新激活表，不会影响其文档或索引。

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

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

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

```
DROP TABLE table_name
```

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

***table\$1name***  
要休眠的表的名称。该表必须已存在且状态为 `ACTIVE`。

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

`tableId` — 您停用表的唯一 ID。

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

```
DROP TABLE VehicleRegistration
```

# Amazon QLDB 中的 FROM（插入、删除或设置）命令
<a name="ql-reference.from"></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 中，以`FROM`开头的语句是 PartiQL 扩展，允许您在文档中插入和删除特定元素。您也可以使用此语句更新文档中的现有元素，类似于[UPDATE](ql-reference.update.md)命令。

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

**Topics**
+ [语法](#ql-reference.from.syntax)
+ [参数](#ql-reference.from.parameters)
+ [嵌套集合](#ql-reference.from.nested-collections)
+ [返回值](#ql-reference.from.return)
+ [示例](#ql-reference.from.examples)
+ [使用驱动程序以编程方式运行](#ql-reference.from.driver)

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

**FROM-INSERT**

在现有文档内插入新元素。要在表格中插入新顶级文档，必须使用[INSERT](ql-reference.insert.md)。

```
FROM table_name [ AS table_alias ] [ BY id_alias ]
[ WHERE condition ]
INSERT INTO element VALUE data [ AT key_name ]
```

**FROM-REMOVE**

移除文档中的现有元素，或者移除整个顶级文档。后者在语义上与传统 [DELETE](ql-reference.delete.md) 语法相同。

```
FROM table_name [ AS table_alias ] [ BY id_alias ]
[ WHERE condition ]
REMOVE element
```

**FROM-SET**

更新文档中的一项或多项元素。如元素不存在，则将其插入。这在语义上与传统 [UPDATE](ql-reference.update.md) 语法相同。

```
FROM table_name [ AS table_alias ] [ BY id_alias ]
[ WHERE condition ]
SET element = data [, element = data, ... ]
```

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

***table\$1name***  
包含要修改数据的用户表的名称。仅默认[用户视图](working.userdata.md)支持 DML 语句。每条语句只能在单个表中运行。  
在此子句中，还可包含嵌套在指定表中的一个或多个集合。有关更多详细信息，请参阅 [嵌套集合](#ql-reference.from.nested-collections)。

**正如 *table\$1alias***  
（可选）用户定义的别名，其范围涵盖要修改的表。`SET`、`REMOVE`、`INSERT INTO` 或 `WHERE`语句中所用的表格别名必须在`FROM`语句中声明。`AS` 关键字是可选的。

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

**哪里 *condition***  
（必需）要修改的文档的选择条件。  
如果省略 `WHERE` 子句，则表中的所有文档都被修改。

***element***  
待创建或修改的文档元素。

***data***  
元素新值。

**在 *key\$1name***  
在要修改的文档中添加的密钥名称。您必须指定相应的 `VALUE` 以及秘钥名称。这是在文档中的特定位置插入新 `AT` 值的必要条件。

## 嵌套集合
<a name="ql-reference.from.nested-collections"></a>

虽然只能对单个表运行 DML 语句，但可以将此表中文档中的嵌套集合指定为其他来源。您为嵌套集合声明的每个别名都可以在 `WHERE`子句和`SET`、`INSERT INTO`或`REMOVE`子句中使用。

例如，以下语句的`FROM` 来源包括 `VehicleRegistration` 表和嵌套 `Owners.SecondaryOwners` 结构。

```
FROM VehicleRegistration r, @r.Owners.SecondaryOwners o
WHERE r.VIN = '1N4AL11D75C109151' AND o.PersonId = 'abc123'
SET o.PersonId = 'def456'
```

此示例更新了特定`SecondaryOwners`列表元素，其中包含`'1N4AL11D75C109151'`中的`VIN`个`VehicleRegistration`文档中的`'abc123'` 的`PersonId`。此表达式允许您按其值而非其索引指定列表中的元素。

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

`documentId` — 您更新或删除的每个文档的唯一 ID。

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

修改文档中的一项元素。如果此元素不存在，则将其插入。

```
FROM Vehicle AS v
WHERE v.VIN = '1N4AL11D75C109151' AND v.Color = 'Silver'
SET v.Color = 'Shiny Gray'
```

修改或插入元素并筛选系统分配的文档`id`元数据字段。

```
FROM Vehicle AS v BY v_id
WHERE v_id = 'documentId'
SET v.Color = 'Shiny Gray'
```

修改文档中`Owners.SecondaryOwners`列表中*第一个*元素的`PersonId`字段。

```
FROM VehicleRegistration AS r
WHERE r.VIN = '1N4AL11D75C109151'
SET r.Owners.SecondaryOwners[0].PersonId = 'abc123'
```

移除文档中的现有元素。

```
FROM Person AS p
WHERE p.GovId = '111-22-3333'
REMOVE p.Address
```

从表格中删除整个文档。

```
FROM Person AS p
WHERE p.GovId = '111-22-3333'
REMOVE p
```

移除`VehicleRegistration`表格中文档中`Owners.SecondaryOwners`列表的*第一个*元素。

```
FROM VehicleRegistration AS r
WHERE r.VIN = '1N4AL11D75C109151'
REMOVE r.Owners.SecondaryOwners[0]
```

`{'Mileage':26500}`以顶级名称/值对的形式插入到表格中的文档中。`Vehicle`

```
FROM Vehicle AS v 
WHERE v.VIN = '1N4AL11D75C109151'
INSERT INTO v VALUE 26500 AT 'Mileage'
```

`{'PersonId':'abc123'}`以名称/值对的形式附加至`VehicleRegistration`表格中`Owners.SecondaryOwners`文档的字段中。请注意，语句`Owners.SecondaryOwners`必须已经存在且必须是列表数据类型才会生效。否则，`INSERT INTO`子句中必须使用关键字`AT`。

```
FROM VehicleRegistration AS r 
WHERE r.VIN = '1N4AL11D75C109151'
INSERT INTO r.Owners.SecondaryOwners VALUE { 'PersonId' : 'abc123' }
```

将`{'PersonId':'abc123'}`以文档现有`Owners.SecondaryOwners`列表中的*首个*元素插入。

```
FROM VehicleRegistration AS r 
WHERE r.VIN = '1N4AL11D75C109151'
INSERT INTO r.Owners.SecondaryOwners VALUE {'PersonId' : 'abc123'} AT 0
```

将多个名称/值对附加到文档中的现有`Owners.SecondaryOwners`列表中。

```
FROM VehicleRegistration AS r 
WHERE r.VIN = '1N4AL11D75C109151'
INSERT INTO r.Owners.SecondaryOwners << {'PersonId' : 'abc123'}, {'PersonId' : 'def456'} >>
```

## 使用驱动程序以编程方式运行
<a name="ql-reference.from.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)

# Amazon QLDB 中的 INSERT 命令
<a name="ql-reference.insert"></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 中，使用`INSERT`命令将一个或多个 Amazon Ion 文档添加到表格中。

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

**Topics**
+ [语法](#ql-reference.insert.syntax)
+ [参数](#ql-reference.insert.parameters)
+ [返回值](#ql-reference.insert.return)
+ [示例](#ql-reference.insert.examples)
+ [使用驱动程序以编程方式运行](#ql-reference.insert.driver)

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

插入单个文档。

```
INSERT INTO table_name VALUE document
```

插入多个文档。

```
INSERT INTO table_name << document, document, ... >>
```

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

***table\$1name***  
要在其中插入数据的用户表的名称。表必须已经存在。仅默认[用户视图](working.userdata.md)支持 DML 语句。

***document***  
有效的 [QLDB 文档](ql-reference.docs.md)。您必须指定至少一个文档。必须用逗号分隔多个文档。  
文档必须用大括号（`{...}`）表示。  
文档中的每个字段名称都是一个区分大小写的 Ion 符号，在 PartiQL 中可以用*单*引号（`'...'`）表示。  
字符串值也用*单*引号（`'...'`）在 PartiQL 中表示。  
任何 Ion 文字都可以用反引号（``...``）表示。

**注意**  
双尖括号（`<<...>>`）表示无序集合（ 在 PartiQL 中称为*数据包*），只有在要插入多个文档时才需要双尖括号。

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

`documentId`— 您插入的每个文档的唯一 ID。

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

插入单个文档。

```
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`
}
```

此语句返回您插入的每个文档的唯一 ID，如下所示。

```
{
    documentId: "2kKuOPNB07D2iTPBrUTWGl"
}
```

插入多个文档。

```
INSERT INTO Person << 
{
    'FirstName' : 'Raul',
    'LastName' : 'Lewis',
    'DOB' : `1963-08-19T`,
    'GovId' : 'LEWISR261LL',
    'GovIdType' : 'Driver License',
    'Address' : '1719 University Street, Seattle, WA, 98109'
},
{
    'FirstName' : 'Brent',
    'LastName' : 'Logan',
    'DOB' : `1967-07-03T`,
    'GovId' : 'LOGANB486CG',
    'GovIdType' : 'Driver License',
    'Address' : '43 Stockert Hollow Road, Everett, WA, 98203'
},
{
    'FirstName' : 'Alexis',
    'LastName' : 'Pena',
    'DOB' : `1974-02-10T`,
    'GovId' : '744 849 301',
    'GovIdType' : 'SSN',
    'Address' : '4058 Melrose Street, Spokane Valley, WA, 99206'
}
>>
```

此语句返回您插入的文档的唯一 ID，如下所示。

```
{
    documentId: "6WXzLscsJ3bDWW97Dy8nyp"
},
{
    documentId: "35e0ToZyTGJ7LGvcwrkX65"
},
{
    documentId: "BVHPcH612o7JROQ4yP8jiH"
}
```

## 使用驱动程序以编程方式运行
<a name="ql-reference.insert.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)

# 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)

# Amazon QLDB 中的更新命令
<a name="ql-reference.update"></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 中，使用`UPDATE`命令来修改文档中一个或多个元素的值。如元素不存在，则将其插入。

您也可以使用此命令在文档中显式插入和删除特定元素，类似于[FROM（插入、删除或设置）](ql-reference.from.md)语句。

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

**Topics**
+ [语法](#ql-reference.update.syntax)
+ [参数](#ql-reference.update.parameters)
+ [返回值](#ql-reference.update.return)
+ [示例](#ql-reference.update.examples)
+ [使用驱动程序以编程方式运行](#ql-reference.update.driver)

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

**UPDATE-SET**

更新文档中的一项或多项元素。如元素不存在，则将其插入。这在语义上与 [FROM-SET](ql-reference.from.md) 语句相同。

```
UPDATE table_name [ AS table_alias ] [ BY id_alias ]
SET element = data [, element = data, ... ]
[ WHERE condition ]
```

**UPDATE-INSERT**

在现有文档内插入新元素。要在表格中插入新顶级文档，必须使用[INSERT](ql-reference.insert.md)。

```
UPDATE table_name [ AS table_alias ] [ BY id_alias ]
INSERT INTO element VALUE data [ AT key_name ]
[ WHERE condition ]
```

**UPDATE-REMOVE**

移除文档中的现有元素，或者移除整个顶级文档。后者在语义上与传统 [DELETE](ql-reference.delete.md) 语法相同。

```
UPDATE table_name [ AS table_alias ] [ BY id_alias ]
REMOVE element
[ WHERE condition ]
```

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

***table\$1name***  
包含要修改数据的用户表的名称。仅默认[用户视图](working.userdata.md)支持 DML 语句。每条语句只能在单个表中运行。

**正如 *table\$1alias***  
（可选）用户定义的别名，其范围涵盖要修改的表。`AS` 关键字是可选的。

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

***element***  
待创建或修改的文档元素。

***data***  
元素新值。

**在 *key\$1name***  
在要修改的文档中添加的密钥名称。您必须指定相应的 `VALUE` 以及秘钥名称。这是在文档中的特定位置插入新 `AT` 值的必要条件。

**哪里 *condition***  
（必需）要修改的文档的选择条件。

**注意**  
如果省略 `WHERE` 子句，则表中的所有文档都被修改。

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

`documentId` — 您更新的每个文档的唯一 ID。

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

更新文档中的表。如果此字段不存在，则将其插入。

```
UPDATE Person AS p
SET p.LicenseNumber = 'HOLLOR123ZZ'
WHERE p.GovId = '111-22-3333'
```

在系统分配的文档`id`元数据字段上进行筛选。

```
UPDATE Person AS p BY pid
SET p.LicenseNumber = 'HOLLOR123ZZ'
WHERE pid = 'documentId'
```

覆盖整个文档。

```
UPDATE Person AS p
SET p = {
    'FirstName' : 'Rosemarie',
    'LastName' : 'Holloway',
    'DOB' : `1977-06-18T`,
    'GovId' : '111-22-3333',
    'GovIdType' : 'Driver License',
    'Address' : '4637 Melrose Street, Ellensburg, WA, 98926'
}
WHERE p.GovId = '111-22-3333'
```

修改文档中`Owners.SecondaryOwners`列表中*第一个*元素的`PersonId`字段。

```
UPDATE VehicleRegistration AS r
SET r.Owners.SecondaryOwners[0].PersonId = 'abc123'
WHERE r.VIN = '1N4AL11D75C109151'
```

`{'Mileage':26500}`以顶级名称/值对的形式插入到表格中的文档中。`Vehicle`

```
UPDATE Vehicle AS v
INSERT INTO v VALUE 26500 AT 'Mileage'
WHERE v.VIN = '1N4AL11D75C109151'
```

`{'PersonId':'abc123'}`以名称/值对的形式附加至`VehicleRegistration`表格中`Owners.SecondaryOwners`文档的字段中。请注意，语句`Owners.SecondaryOwners`必须已经存在且必须是列表数据类型才会生效。否则，`INSERT INTO`子句中必须使用关键字`AT`。

```
UPDATE VehicleRegistration AS r
INSERT INTO r.Owners.SecondaryOwners VALUE { 'PersonId' : 'abc123' }
WHERE r.VIN = '1N4AL11D75C109151'
```

将`{'PersonId':'abc123'}`以文档现有`Owners.SecondaryOwners`列表中的*首个*元素插入。

```
UPDATE VehicleRegistration AS r
INSERT INTO r.Owners.SecondaryOwners VALUE {'PersonId' : 'abc123'} AT 0
WHERE r.VIN = '1N4AL11D75C109151'
```

将多个名称/值对附加到文档中的现有`Owners.SecondaryOwners`列表中。

```
UPDATE VehicleRegistration AS r
INSERT INTO r.Owners.SecondaryOwners << {'PersonId' : 'abc123'}, {'PersonId' : 'def456'} >>
WHERE r.VIN = '1N4AL11D75C109151'
```

移除文档中的现有元素。

```
UPDATE Person AS p
REMOVE p.Address
WHERE p.GovId = '111-22-3333'
```

从表格中删除整个文档。

```
UPDATE Person AS p
REMOVE p
WHERE p.GovId = '111-22-3333'
```

移除`VehicleRegistration`表格中文档中`Owners.SecondaryOwners`列表的*第一个*元素。

```
UPDATE VehicleRegistration AS r
REMOVE r.Owners.SecondaryOwners[0]
WHERE r.VIN = '1N4AL11D75C109151'
```

## 使用驱动程序以编程方式运行
<a name="ql-reference.update.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)

# Amazon QLDB 中的 UNDROP TABLE 命令
<a name="ql-reference.undrop-table"></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 中，使用 `UNDROP TABLE` 命令重新激活之前删除的表（即已停用）。停用或重新激活表，不会影响其文档或索引。

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

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

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

```
UNDROP TABLE "tableId"
```

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

**"*tableId*"**  
待索引的表的唯一 ID，用双引号表示。  
该表必须先前已被删除，这意味着它存在于[系统目录表](working.catalog.md)，`information_schema.user_tables`并且状态为`INACTIVE`。也不能存在同名活动现有表。

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

`tableId` - 您重新激活的表的唯一 ID。

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

```
UNDROP TABLE "5PLf9SXwndd63lPaSIa0O6"
```

# Amazon QLDB 中的 PartiQL 函数
<a name="ql-functions"></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 支持以下 SQL 标准函数的内置版本。

**注意**  
QLDB 当前不支持任何未包含在此列表中的 SQL 函数。  
本函数参考基于 PartiQL 文档[内置函数](https://github.com/partiql/partiql-lang-kotlin/blob/main/docs/wiki/documentation/Functions.md#built-in-functions)。

**未知类型（空且缺失）传播**

除非另有说明，否则所有函数都会传播空值和缺失参数值。如果任何函数参数为`NULL` 或 `MISSING`，则`NULL` 或 `MISSING`的*传播*定义为返回`NULL`。以下是这种传播示例。

```
CHAR_LENGTH(null)    -- null
CHAR_LENGTH(missing) -- null (also returns null)
```

## 聚合函数
<a name="ql-functions.aggregate"></a>
+ [AVG](ql-functions.avg.md)
+ [COUNT](ql-functions.count.md)
+ [MAX](ql-functions.max.md)
+ [MIN](ql-functions.min.md)
+ [SIZE](ql-functions.size.md)
+ [SUM](ql-functions.sum.md)

## 条件函数
<a name="ql-functions.conditional"></a>
+ [COALESCE](ql-functions.coalesce.md)
+ [EXISTS](ql-functions.exists.md)
+ [NULLIF](ql-functions.nullif.md)

## 日期和时间函数
<a name="ql-functions.date"></a>
+ [DATE\$1ADD](ql-functions.date_add.md)
+ [DATE\$1DIFF](ql-functions.date_diff.md)
+ [EXTRACT](ql-functions.extract.md)
+ [UTCNOW](ql-functions.utcnow.md)

## 标量函数
<a name="ql-functions.scalar"></a>
+ [TXID](ql-functions.txid.md)

## 字符串函数
<a name="ql-functions.string"></a>
+ [CHAR\$1LENGTH](ql-functions.char_length.md)
+ [CHARACTER\$1LENGTH](ql-functions.character_length.md)
+ [LOWER](ql-functions.lower.md)
+ [SUBSTRING](ql-functions.substring.md)
+ [TRIM](ql-functions.trim.md)
+ [UPPER](ql-functions.upper.md)

## 数据类型格式设置函数
<a name="ql-functions.formatting"></a>
+ [CAST](ql-functions.cast.md)
+ [TO\$1STRING](ql-functions.to_string.md)
+ [TO\$1TIMESTAMP](ql-functions.to_timestamp.md)

# Amazon QLDB 中的 AVG 函数
<a name="ql-functions.avg"></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 中，使用 `AVG` 函数返回输入表达式值的平均值（算术平均值）。此函数处理数值，而忽略空值或缺失值。

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

```
AVG ( expression )
```

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

*expression*  
对其执行函数的数字数据类型字段名称或表达式。

## 数据类型
<a name="ql-functions.avg.data-types"></a>

支持的参数类型：
+ `int`
+ `decimal`
+ `float`

返回类型: `decimal`

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

```
SELECT AVG(r.PendingPenaltyTicketAmount) FROM VehicleRegistration r  -- 147.19
SELECT AVG(a) FROM << { 'a' : 1 }, { 'a': 2 }, { 'a': 3 } >>         -- 2.
```

## 相关函数
<a name="ql-functions.avg.related"></a>
+ [COUNT](ql-functions.count.md)
+ [MAX](ql-functions.max.md)
+ [MIN](ql-functions.min.md)
+ [SIZE](ql-functions.size.md)
+ [SUM](ql-functions.sum.md)

# Amazon QLDB 中的 CAST 功能
<a name="ql-functions.cast"></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 中，使用 `CAST` 函数将给定表达式计算为一个值，并将该值转换为指定目标数据类型。如果无法进行转换，则该函数将返回错误。

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

```
CAST ( expression AS type )
```

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

*expression*  
评估函数转换值的字段名称或表达式。转换 null 值将返回 null。此参数可以是任何支持[数据类型](ql-reference.data-types.md)的参数。

*type*  
要转换的目标数据类型名称。此参数可以是任何支持[数据类型](ql-reference.data-types.md)的参数之一。

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

*type*参数指定的数据类型。

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

以下示例显示了未知类型（`NULL`或`MISSING`）传播。

```
CAST(null    AS null)    -- null 
CAST(missing AS null)    -- null 
CAST(missing AS missing) -- missing
CAST(null    AS missing) -- missing
CAST(null    AS boolean) -- null (null AS any data type name results in null)
CAST(missing AS boolean) -- missing (missing AS any data type name results in missing)
```

任何非未知类型的值都不能转换为 `NULL`或`MISSING`。

```
CAST(true AS null)    -- error 
CAST(true AS missing) -- error
CAST(1    AS null)    -- error
CAST(1    AS missing) -- error
```

以下示例显示了转换 `AS boolean`。

```
CAST(true      AS boolean) -- true no-op
CAST(0         AS boolean) -- false
CAST(1         AS boolean) -- true
CAST(`1e0`     AS boolean) -- true (float)
CAST(`1d0`     AS boolean) -- true (decimal)
CAST('a'       AS boolean) -- false
CAST('true'    AS boolean) -- true (SqlName string 'true')
CAST(`'true'`  AS boolean) -- true (Ion symbol `'true'`)
CAST(`'false'` AS boolean) -- false (Ion symbol `'false'`)
```

以下示例显示了转换 `AS integer`。

```
CAST(true   AS integer) -- 1
CAST(false  AS integer) -- 0
CAST(1      AS integer) -- 1
CAST(`1d0`  AS integer) -- 1
CAST(`1d3`  AS integer) -- 1000
CAST(1.00   AS integer) -- 1
CAST(1.45   AS integer) -- 1
CAST(1.75   AS integer) -- 1
CAST('12'   AS integer) -- 12
CAST('aa'   AS integer) -- error
CAST(`'22'` AS integer) -- 22
CAST(`'x'`  AS integer) -- error
```

以下示例显示了转换 `AS float`。

```
CAST(true   AS float) -- 1e0
CAST(false  AS float) -- 0e0
CAST(1      AS float) -- 1e0
CAST(`1d0`  AS float) -- 1e0
CAST(`1d3`  AS float) -- 1000e0
CAST(1.00   AS float) -- 1e0
CAST('12'   AS float) -- 12e0
CAST('aa'   AS float) -- error
CAST(`'22'` AS float) -- 22e0
CAST(`'x'`  AS float) -- error
```

以下示例显示了转换 `AS decimal`。

```
CAST(true   AS decimal) -- 1.
CAST(false  AS decimal) -- 0.
CAST(1      AS decimal) -- 1.
CAST(`1d0`  AS decimal) -- 1. (REPL printer serialized to 1.)
CAST(`1d3`  AS decimal) -- 1d3
CAST(1.00   AS decimal) -- 1.00
CAST('12'   AS decimal) -- 12.
CAST('aa'   AS decimal) -- error
CAST(`'22'` AS decimal) -- 22.
CAST(`'x'`  AS decimal) -- error
```

以下示例显示了转换 `AS timestamp`。

```
CAST(`2001T`                      AS timestamp) -- 2001T
CAST('2001-01-01T'                AS timestamp) -- 2001-01-01T
CAST(`'2010-01-01T00:00:00.000Z'` AS timestamp) -- 2010-01-01T00:00:00.000Z
CAST(true                         AS timestamp) -- error
CAST(2001                         AS timestamp) -- error
```

以下示例显示了转换 `AS symbol`。

```
CAST(`'xx'`                     AS symbol) -- xx (`'xx'` is an Ion symbol)
CAST('xx'                       AS symbol) -- xx ('xx' is a string)
CAST(42                         AS symbol) -- '42'
CAST(`1e0`                      AS symbol) -- '1.0'
CAST(`1d0`                      AS symbol) -- '1'
CAST(true                       AS symbol) -- 'true'
CAST(false                      AS symbol) -- 'false'
CAST(`2001T`                    AS symbol) -- '2001T'
CAST(`2001-01-01T00:00:00.000Z` AS symbol) -- '2001-01-01T00:00:00.000Z'
```

以下示例显示了转换 `AS string`。

```
CAST(`'xx'`                     AS string) -- "xx" (`'xx'` is an Ion symbol)
CAST('xx'                       AS string) -- "xx" ('xx' is a string)
CAST(42                         AS string) -- "42"
CAST(`1e0`                      AS string) -- "1.0"
CAST(`1d0`                      AS string) -- "1"
CAST(true                       AS string) -- "true"
CAST(false                      AS string) -- "false"
CAST(`2001T`                    AS string) -- "2001T"
CAST(`2001-01-01T00:00:00.000Z` AS string) -- "2001-01-01T00:00:00.000Z"
```

以下示例显示了转换 `AS struct`。

```
CAST(`{ a: 1 }` AS struct) -- {a:1}
CAST(true       AS struct) -- err
```

以下示例显示了转换 `AS list`。

```
CAST(`[1, 2, 3]`        AS list) -- [1,2,3]
CAST(<<'a', { 'b':2 }>> AS list) -- ["a",{'b':2}]
CAST({ 'b':2 }          AS list) -- error
```

以下示例为可运行语句，其中包括前面的一些示例。

```
SELECT CAST(true AS integer) FROM << 0 >>            -- 1
SELECT CAST('2001-01-01T' AS timestamp) FROM << 0 >> -- 2001-01-01T
SELECT CAST('xx' AS symbol) FROM << 0 >>             -- xx
SELECT CAST(42 AS string) FROM << 0 >>               -- "42"
```

## 相关函数
<a name="ql-functions.cast.related"></a>
+ [TO\$1STRING](ql-functions.to_string.md)
+ [TO\$1TIMESTAMP](ql-functions.to_timestamp.md)

# Amazon QLDB 中的 CHAR\$1LENGTH 函数
<a name="ql-functions.char_length"></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 中，使用`CHAR_LENGTH`函数返回指定字符串中的字符数，其中*字符* 定义为单个 unicode 代码点。

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

```
CHAR_LENGTH ( string )
```

`CHAR_LENGTH`是[Amazon QLDB 中的 CHARACTER\$1LENGTH 函数](ql-functions.character_length.md)的同义词。

## 参数
<a name="ql-functions.char_length.arguments"></a>

*string*  
函数计算的数据类型的 `string` 字段名称或表达式。

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

`int`

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

```
SELECT CHAR_LENGTH('') FROM << 0 >>        -- 0
SELECT CHAR_LENGTH('abcdefg') FROM << 0 >> -- 7
SELECT CHAR_LENGTH('eࠫ') FROM << 0 >>      -- 2 (because 'eࠫ' is two code points: the letter 'e' and combining character U+032B)
```

## 相关函数
<a name="ql-functions.char_length.related"></a>
+ [LOWER](ql-functions.lower.md)
+ [SUBSTRING](ql-functions.substring.md)
+ [TRIM](ql-functions.trim.md)
+ [UPPER](ql-functions.upper.md)

# Amazon QLDB 中的 CHARACTER\$1LENGTH 函数
<a name="ql-functions.character_length"></a>

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

`CHAR_LENGTH` 函数的同义词。

请参阅 [Amazon QLDB 中的 CHAR\$1LENGTH 函数](ql-functions.char_length.md)。

# Amazon QLDB 中的 COALESCE 函数
<a name="ql-functions.coalesce"></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 中，给定一个或多个参数列表，使用`COALESCE`函数按从左到右的顺序计算参数，并返回第一个不是未知类型值（`NULL` 或 `MISSING`）。如果所有参数类型均未知，则结果为`NULL`。

该 `COALESCE` 函数不会传 播`NULL`和`MISSING`。

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

```
COALESCE ( expression [, expression, ... ] )
```

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

*expression*  
函数计算的、一个或多个字段名称或表达式的列表。每个参数都可以是任何支持的 [数据类型](ql-reference.data-types.md)。

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

任何支持数据类型。返回类型为`NULL`，或与计算非空值和非缺失值的第一个表达式的类型相同。

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

```
SELECT COALESCE(1, null) FROM << 0 >>         -- 1
SELECT COALESCE(null, null, 1) FROM << 0 >>   -- 1
SELECT COALESCE(null, 'string') FROM << 0 >>  -- "string"
```

## 相关函数
<a name="ql-functions.coalesce.related"></a>
+ [EXISTS](ql-functions.exists.md)
+ [NULLIF](ql-functions.nullif.md)

# Amazon QLDB 中的 COUNT 函数
<a name="ql-functions.count"></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 中，使用函数`COUNT` 返回由给定表达式定义的文档数量。此函数具有两种变体：
+ `COUNT(*)` — 计算目标表中的所有文档，无论它们是否包含空值或缺失值。
+ `COUNT(expression)` — 计算特定的现有字段或表达式中具有非空值的文档数。

**警告**  
`COUNT` 函数未经过优化，因此我们不建议在没有索引查询的情况下使用它。当您在没有索引查找的情况下运行查询时，它会调用全表扫描。这可能会导致大型表出现性能问题，包括并发冲突与事务超时。  
为避免表扫描，必须在索引字段或文档 ID 上使用*相等*运算符（`=`或`IN`）运行带有`WHERE`谓词子句的语句。有关更多信息，请参阅 [优化查询性能](working.optimize.md)。

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

```
COUNT ( * | expression )
```

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

*expression*  
对其执行函数的字段名称或表达式。此参数可以是任何支持[数据类型](ql-reference.data-types.md)的参数。

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

`int`

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

```
SELECT COUNT(*) FROM VehicleRegistration r WHERE r.LicensePlateNumber = 'CA762X' -- 1
SELECT COUNT(r.VIN) FROM Vehicle r WHERE r.VIN = '1N4AL11D75C109151'             -- 1
SELECT COUNT(a) FROM << { 'a' : 1 }, { 'a': 2 }, { 'a': 3 } >>                   -- 3
```

## 相关函数
<a name="ql-functions.count.related"></a>
+ [AVG](ql-functions.avg.md)
+ [MAX](ql-functions.max.md)
+ [MIN](ql-functions.min.md)
+ [SIZE](ql-functions.size.md)
+ [SUM](ql-functions.sum.md)

# Amazon QLDB 中的 DATE\$1ADD 函数
<a name="ql-functions.date_add"></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 中，使用`DATE_ADD`函数将给定的时间戳值按指定的间隔递增。

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

```
DATE_ADD( datetimepart, interval, timestamp )
```

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

*datetimepart*  
对其执行函数的日期或时间段。该参数可以是下列项之一：  
+ `year`
+ `month`
+ `day`
+ `hour`
+ `minute`
+ `second`

*interval*  
指定要与给定值相加的间隔的整数*timestamp*。负整数减去时间间隔。

*timestamp*  
函数递增数据类型的`timestamp`字段名称或表达式。  
Ion 时间戳文本值可以用反引号（``...``）表示。有关时间戳值的格式详细信息和示例，请参阅 Amazon Ion 规格文档中的[时间戳](https://amzn.github.io/ion-docs/docs/spec.html#timestamp)。

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

`timestamp`

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

```
DATE_ADD(year, 5, `2010-01-01T`)                -- 2015-01-01T
DATE_ADD(month, 1, `2010T`)                     -- 2010-02T (result adds precision as necessary)
DATE_ADD(month, 13, `2010T`)                    -- 2011-02T (2010T is equivalent to 2010-01-01T00:00:00.000Z)
DATE_ADD(day, -1, `2017-01-10T`)                -- 2017-01-09T
DATE_ADD(hour, 1, `2017T`)                      -- 2017-01-01T01:00Z
DATE_ADD(hour, 1, `2017-01-02T03:04Z`)          -- 2017-01-02T04:04Z
DATE_ADD(minute, 1, `2017-01-02T03:04:05.006Z`) -- 2017-01-02T03:05:05.006Z
DATE_ADD(second, 1, `2017-01-02T03:04:05.006Z`) -- 2017-01-02T03:04:06.006Z

-- Runnable statements
SELECT DATE_ADD(year, 5, `2010-01-01T`) FROM << 0 >> -- 2015-01-01T
SELECT DATE_ADD(day, -1, `2017-01-10T`) FROM << 0 >> -- 2017-01-09T
```

## 相关函数
<a name="ql-functions.date_add.related"></a>
+ [DATE\$1DIFF](ql-functions.date_diff.md)
+ [EXTRACT](ql-functions.extract.md)
+ [TO\$1STRING](ql-functions.to_string.md)
+ [TO\$1TIMESTAMP](ql-functions.to_timestamp.md)
+ [UTCNOW](ql-functions.utcnow.md)

# Amazon QLDB 中的 DATE\$1DIFF 函数
<a name="ql-functions.date_diff"></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 中，使用 `DATE_DIFF` 函数返回两个给定时间戳中指定日期部分之间的差值。

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

```
DATE_DIFF( datetimepart, timestamp1, timestamp2 )
```

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

*datetimepart*  
对其执行函数的日期或时间段。该参数可以是下列项之一：  
+ `year`
+ `month`
+ `day`
+ `hour`
+ `minute`
+ `second`

*timestamp1*, *timestamp2*  
函数比较的数据类型 `timestamp` 的两个字段名称或表达式。如果晚*timestamp2*于*timestamp1*，则结果为阳性。如果早*timestamp2*于*timestamp1*，则结果为负。  
Ion 时间戳文本值可以用反引号（``...``）表示。有关时间戳值的格式详细信息和示例，请参阅 Amazon Ion 规格文档中的[时间戳](https://amzn.github.io/ion-docs/docs/spec.html#timestamp)。

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

`int`

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

```
DATE_DIFF(year, `2010-01-01T`, `2011-01-01T`)            -- 1
DATE_DIFF(year, `2010-12T`, `2011-01T`)                  -- 0 (must be at least 12 months apart to evaluate as a 1 year difference)
DATE_DIFF(month, `2010T`, `2010-05T`)                    -- 4 (2010T is equivalent to 2010-01-01T00:00:00.000Z)
DATE_DIFF(month, `2010T`, `2011T`)                       -- 12
DATE_DIFF(month, `2011T`, `2010T`)                       -- -12
DATE_DIFF(month, `2010-12-31T`, `2011-01-01T`)           -- 0 (must be at least a full month apart to evaluate as a 1 month difference)
DATE_DIFF(day, `2010-01-01T23:00Z`, `2010-01-02T01:00Z`) -- 0 (must be at least 24 hours apart to evaluate as a 1 day difference)

-- Runnable statements
SELECT DATE_DIFF(year, `2010-01-01T`, `2011-01-01T`) FROM << 0 >> -- 1
SELECT DATE_DIFF(month, `2010T`, `2010-05T`) FROM << 0 >>         -- 4
```

## 相关函数
<a name="ql-functions.date_diff.related"></a>
+ [DATE\$1ADD](ql-functions.date_add.md)
+ [EXTRACT](ql-functions.extract.md)
+ [TO\$1STRING](ql-functions.to_string.md)
+ [TO\$1TIMESTAMP](ql-functions.to_timestamp.md)
+ [UTCNOW](ql-functions.utcnow.md)

# Amazon QLDB 中存在函数
<a name="ql-functions.exists"></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 值，如果该值是非空集合则使用`EXISTS`函数返回`TRUE`。否则，此函数返回 `FALSE`。如果输入 `EXISTS` 不是容器，则结果为`FALSE`。

该 `EXISTS` 函数不会传 播`NULL`和`MISSING`。

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

```
EXISTS ( value )
```

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

*value*  
函数评估的字段名称或表达式。此参数可以是任何支持[数据类型](ql-reference.data-types.md)的参数。

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

`bool`

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

```
EXISTS(`[]`)        -- false (empty list)
EXISTS(`[1, 2, 3]`) -- true (non-empty list)
EXISTS(`[missing]`) -- true (non-empty list)
EXISTS(`{}`)        -- false (empty struct)
EXISTS(`{ a: 1 }`)  -- true (non-empty struct)
EXISTS(`()`)        -- false (empty s-expression)
EXISTS(`(+ 1 2)`)   -- true (non-empty s-expression)
EXISTS(1)           -- false
EXISTS(`2017T`)     -- false
EXISTS(null)        -- false
EXISTS(missing)     -- error

-- Runnable statements
SELECT EXISTS(`[]`) FROM << 0 >>        -- false
SELECT EXISTS(`[1, 2, 3]`) FROM << 0 >> -- true
```

## 相关函数
<a name="ql-functions.exists.related"></a>
+ [COALESCE](ql-functions.coalesce.md)
+ [NULLIF](ql-functions.nullif.md)

# Amazon QLDB 中的 EXTRACT 函数
<a name="ql-functions.extract"></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 中，使用 `EXTRACT` 函数返回给定时间戳中指定日期或时间段的整数值。

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

```
EXTRACT ( datetimepart FROM timestamp )
```

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

*datetimepart*  
函数提取的日期或时间段。该参数可以是下列项之一：  
+ `year`
+ `month`
+ `day`
+ `hour`
+ `minute`
+ `second`
+ `timezone_hour`
+ `timezone_minute`

*timestamp*  
函数从中提取的数据类型 `timestamp` 的字段名称或表达式。如果此参数是未知类型（`NULL`或`MISSING`），则函数返回`NULL`。  
Ion 时间戳文本值可以用反引号（``...``）表示。有关时间戳值的格式详细信息和示例，请参阅 Amazon Ion 规格文档中的[时间戳](https://amzn.github.io/ion-docs/docs/spec.html#timestamp)。

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

`int`

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

```
EXTRACT(YEAR FROM `2010-01-01T`)                           -- 2010
EXTRACT(MONTH FROM `2010T`)                                -- 1 (equivalent to 2010-01-01T00:00:00.000Z)
EXTRACT(MONTH FROM `2010-10T`)                             -- 10
EXTRACT(HOUR FROM `2017-01-02T03:04:05+07:08`)             -- 3
EXTRACT(MINUTE FROM `2017-01-02T03:04:05+07:08`)           -- 4
EXTRACT(TIMEZONE_HOUR FROM `2017-01-02T03:04:05+07:08`)    -- 7
EXTRACT(TIMEZONE_MINUTE FROM `2017-01-02T03:04:05+07:08`)  -- 8

-- Runnable statements
SELECT EXTRACT(YEAR FROM `2010-01-01T`) FROM << 0 >> -- 2010
SELECT EXTRACT(MONTH FROM `2010T`) FROM << 0 >>      -- 1
```

## 相关函数
<a name="ql-functions.extract.related"></a>
+ [DATE\$1ADD](ql-functions.date_add.md)
+ [DATE\$1DIFF](ql-functions.date_diff.md)
+ [TO\$1STRING](ql-functions.to_string.md)
+ [TO\$1TIMESTAMP](ql-functions.to_timestamp.md)
+ [UTCNOW](ql-functions.utcnow.md)

# Amazon QLDB 中的 LOWER 函数
<a name="ql-functions.lower"></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 中，使用函数 `LOWER` 将给定字符串中的所有大写字符转换为小写字符。

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

```
LOWER ( string )
```

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

*string*  
函数转换的数据类型的 `string` 字段名称或表达式。

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

`string`

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

```
SELECT LOWER('AbCdEfG!@#$') FROM << 0 >> -- 'abcdefg!@#$'
```

## 相关函数
<a name="ql-functions.lower.related"></a>
+ [CHAR\$1LENGTH](ql-functions.char_length.md)
+ [SUBSTRING](ql-functions.substring.md)
+ [TRIM](ql-functions.trim.md)
+ [UPPER](ql-functions.upper.md)

# Amazon QLDB 中的 MAX 函数
<a name="ql-functions.max"></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 中，使用`MAX`函数返回一组数值中的最大值。

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

```
MAX ( expression )
```

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

*expression*  
对其执行函数的数字数据类型字段名称或表达式。

## 数据类型
<a name="ql-functions.max.data-types"></a>

支持的参数类型：
+ `int`
+ `decimal`
+ `float`

支持的返回类型：
+ `int`
+ `decimal`
+ `float`

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

```
SELECT MAX(r.PendingPenaltyTicketAmount) FROM VehicleRegistration r  -- 442.30
SELECT MAX(a) FROM << { 'a' : 1 }, { 'a': 2 }, { 'a': 3 } >>         -- 3
```

## 相关函数
<a name="ql-functions.max.related"></a>
+ [AVG](ql-functions.avg.md)
+ [COUNT](ql-functions.count.md)
+ [MIN](ql-functions.min.md)
+ [SIZE](ql-functions.size.md)
+ [SUM](ql-functions.sum.md)

# Amazon QLDB 中的 MIN 函数
<a name="ql-functions.min"></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 中，使用`MIN` 函数返回一组数值中的最小值。

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

```
MIN ( expression )
```

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

*expression*  
对其执行函数的数字数据类型字段名称或表达式。

## 数据类型
<a name="ql-functions.min.data-types"></a>

支持的参数类型：
+ `int`
+ `decimal`
+ `float`

支持的返回类型：
+ `int`
+ `decimal`
+ `float`

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

```
SELECT MIN(r.PendingPenaltyTicketAmount) FROM VehicleRegistration r  -- 30.45
SELECT MIN(a) FROM << { 'a' : 1 }, { 'a': 2 }, { 'a': 3 } >>         -- 1
```

## 相关函数
<a name="ql-functions.min.related"></a>
+ [AVG](ql-functions.avg.md)
+ [COUNT](ql-functions.count.md)
+ [MAX](ql-functions.max.md)
+ [SIZE](ql-functions.size.md)
+ [SUM](ql-functions.sum.md)

# Amazon QLDB 中的 NULLIF 函数
<a name="ql-functions.nullif"></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 中，指定两个表达式，如果两个表达式的计算结果为相同值，则使用`NULLIF` 函数返回 `NULL`。否则该函数会返回空，对其执行第一个表达式计算结果。

该 `NULLIF` 函数不会传播 `NULL`和`MISSING`。

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

```
NULLIF ( expression1, expression2 )
```

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

*expression1*, *expression2*  
函数对比的两个字段名称或表达式。这些参数可以是任何支持[数据类型](ql-reference.data-types.md)的参数。

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

任何支持数据类型。返回类型为 `NULL` 或与第一个表达式的类型相同。

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

```
NULLIF(1, 1)             -- null
NULLIF(1, 2)             -- 1
NULLIF(1.0, 1)           -- null
NULLIF(1, '1')           -- 1
NULLIF([1], [1])         -- null
NULLIF(1, NULL)          -- 1
NULLIF(NULL, 1)          -- null
NULLIF(null, null)       -- null
NULLIF(missing, null)    -- null
NULLIF(missing, missing) -- null

-- Runnable statements
SELECT NULLIF(1, 1) FROM << 0 >>   -- null
SELECT NULLIF(1, '1') FROM << 0 >> -- 1
```

## 相关函数
<a name="ql-functions.nullif.related"></a>
+ [COALESCE](ql-functions.coalesce.md)
+ [EXISTS](ql-functions.exists.md)

# Amazon QLDB 中的 SIZE 函数
<a name="ql-functions.size"></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 中，使用 `SIZE` 函数返回给定容器数据类型（列表、结构或袋子）中元素的数量。

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

```
SIZE ( container )
```

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

*container*  
函数运行其上的容器字段名称或表达式。

## 数据类型
<a name="ql-functions.size.data-types"></a>

支持的参数类型：
+ 列表
+ 结构
+ 包

返回类型: `int`

如果的输入 `SIZE` 不是容器，则该函数会引发错误。

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

```
SIZE(`[]`)                   -- 0
SIZE(`[null]`)               -- 1
SIZE(`[1,2,3]`)              -- 3
SIZE(<<'foo', 'bar'>>)       -- 2
SIZE(`{foo: bar}`)           -- 1 (number of key-value pairs)
SIZE(`[{foo: 1}, {foo: 2}]`) -- 2
SIZE(12)                     -- error

-- Runnable statements
SELECT SIZE(`[]`) FROM << 0 >>      -- 0
SELECT SIZE(`[1,2,3]`) FROM << 0 >> -- 3
```

## 相关函数
<a name="ql-functions.size.related"></a>
+ [AVG](ql-functions.avg.md)
+ [COUNT](ql-functions.count.md)
+ [MAX](ql-functions.max.md)
+ [MIN](ql-functions.min.md)
+ [SUM](ql-functions.sum.md)

# Amazon QLDB 中的 SUBSTRING 函数
<a name="ql-functions.substring"></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 中，使用 `SUBSTRING` 函数从给定字符串返回子字符串。子字符串从指定起始索引开始，以字符串的最后一个字符或指定长度结束。

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

```
SUBSTRING ( string, start-index [, length ] )
```

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

*string*  
要从中提取子字符串的数据类型`string`的字段名称或表达式。

*start-index*  
*string*从中开始提取的起始位置。此数字可以为负。  
的第一个字符*string*的索引为 1。

*length*  
（可选）要从中提取的字符（代码点）数*string*，起点*start-index*为 (*start-index*\$1*length*)-1。换句话说，就是子字符串的长度。此数字不能为负。  
如果未提供此参数，则该函数将一直运行到结束*string*。

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

`string`

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

```
SUBSTRING('123456789', 0)      -- '123456789'
SUBSTRING('123456789', 1)      -- '123456789'
SUBSTRING('123456789', 2)      -- '23456789'
SUBSTRING('123456789', -4)     -- '123456789'
SUBSTRING('123456789', 0, 999) -- '123456789'
SUBSTRING('123456789', 0, 2)   -- '1'
SUBSTRING('123456789', 1, 999) -- '123456789'
SUBSTRING('123456789', 1, 2)   -- '12'
SUBSTRING('1', 1, 0)           -- ''
SUBSTRING('1', 1, 0)           -- ''
SUBSTRING('1', -4, 0)          -- ''
SUBSTRING('1234', 10, 10)      -- ''

-- Runnable statements
SELECT SUBSTRING('123456789', 1) FROM << 0 >>    -- "123456789"
SELECT SUBSTRING('123456789', 1, 2) FROM << 0 >> -- "12"
```

## 相关函数
<a name="ql-functions.substring.related"></a>
+ [CHAR\$1LENGTH](ql-functions.char_length.md)
+ [LOWER](ql-functions.lower.md)
+ [TRIM](ql-functions.trim.md)
+ [UPPER](ql-functions.upper.md)

# Amazon QLDB 中的 SUM 函数
<a name="ql-functions.sum"></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 中，使用 `SUM` 函数返回输入字段值或表达式值的和。此函数处理数值，而忽略空值或缺失值。

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

```
SUM ( expression )
```

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

*expression*  
对其执行函数的数字数据类型字段名称或表达式。

## 数据类型
<a name="ql-functions.sum.data-types"></a>

支持的参数类型：
+ `int`
+ `decimal`
+ `float`

支持的返回类型：
+ `int` — 对于整数参数
+ `decimal` — 对于十进制或浮点数参数

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

```
SELECT SUM(r.PendingPenaltyTicketAmount) FROM VehicleRegistration r  -- 735.95
SELECT SUM(a) FROM << { 'a' : 1 }, { 'a': 2 }, { 'a': 3 } >>         -- 6
```

## 相关函数
<a name="ql-functions.sum.related"></a>
+ [AVG](ql-functions.avg.md)
+ [COUNT](ql-functions.count.md)
+ [MAX](ql-functions.max.md)
+ [MIN](ql-functions.min.md)
+ [SIZE](ql-functions.size.md)

# Amazon QLDB 中的 TO\$1STRING 函数
<a name="ql-functions.to_string"></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 中，使用 `TO_STRING` 函数以指定格式模式返回给定时间戳字符串表示形式。

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

```
TO_STRING ( timestamp, 'format' )
```

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

*timestamp*  
函数转换为字符串的数据类型 `timestamp` 的字段名称或表达式。  
Ion 时间戳文本值可以用反引号（``...``）表示。有关时间戳值的格式详细信息和示例，请参阅 Amazon Ion 规格文档中的[时间戳](https://amzn.github.io/ion-docs/docs/spec.html#timestamp)。

*format*  
指定结果格式模式的字符串文本，按其日期部分表示格式。有关有效格式，请参阅[时间戳格式字符串](ql-functions.timestamp-format.md)。

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

`string`

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

```
TO_STRING(`1969-07-20T20:18Z`, 'MMMM d, y')                     -- "July 20, 1969"
TO_STRING(`1969-07-20T20:18Z`, 'MMM d, yyyy')                   -- "Jul 20, 1969"
TO_STRING(`1969-07-20T20:18Z`, 'M-d-yy')                        -- "7-20-69"
TO_STRING(`1969-07-20T20:18Z`, 'MM-d-y')                        -- "07-20-1969"
TO_STRING(`1969-07-20T20:18Z`, 'MMMM d, y h:m a')               -- "July 20, 1969 8:18 PM"
TO_STRING(`1969-07-20T20:18Z`, 'y-MM-dd''T''H:m:ssX')           -- "1969-07-20T20:18:00Z"
TO_STRING(`1969-07-20T20:18+08:00Z`, 'y-MM-dd''T''H:m:ssX')     -- "1969-07-20T20:18:00Z"
TO_STRING(`1969-07-20T20:18+08:00`, 'y-MM-dd''T''H:m:ssXXXX')   -- "1969-07-20T20:18:00+0800"
TO_STRING(`1969-07-20T20:18+08:00`, 'y-MM-dd''T''H:m:ssXXXXX')  -- "1969-07-20T20:18:00+08:00"

-- Runnable statements
SELECT TO_STRING(`1969-07-20T20:18Z`, 'MMMM d, y') FROM << 0 >>           -- "July 20, 1969"
SELECT TO_STRING(`1969-07-20T20:18Z`, 'y-MM-dd''T''H:m:ssX') FROM << 0 >> -- "1969-07-20T20:18:00Z"
```

## 相关函数
<a name="ql-functions.to_string.related"></a>
+ [CAST](ql-functions.cast.md)
+ [DATE\$1ADD](ql-functions.date_add.md)
+ [DATE\$1DIFF](ql-functions.date_diff.md)
+ [EXTRACT](ql-functions.extract.md)
+ [TO\$1TIMESTAMP](ql-functions.to_timestamp.md)
+ [UTCNOW](ql-functions.utcnow.md)

# Amazon QLDB 中的 TO\$1TIMESTAMP 函数
<a name="ql-functions.to_timestamp"></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，如果给定一个表示时间戳的字符串，则使用函数`TO_TIMESTAMP`将该字符串转换为`timestamp`数据类型。这是 `TO_STRING` 的逆运算。

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

```
TO_TIMESTAMP ( string [, 'format' ] )
```

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

*string*  
函数转换为时间戳的数据类型 `string` 的字段名称或表达式。

*format*  
（可选）用日期部分定义输入*string*格式模式的字符串文字。有关有效格式，请参阅[时间戳格式字符串](ql-functions.timestamp-format.md)。  
如果省略此参数，则该函数假定采用[标准 Ion 时间戳](http://amzn.github.io/ion-docs/docs/spec.html#timestamp)的格式。*string*建议使用此函数解析 Ion 时间戳。  
使用单字符格式符号（例如`y`、`M`、`d`、`H`、`h`、`m`、`s`）时，可选择零填充，但是零填充变体为必填项（如`yyyy`、`MM`、`dd`、`HH`、 `hh`、`mm`、`ss`）。  
对两位数年份（格式符号`yy`）给予特殊处理。大于或等于 70 的值加上 1900，小于 70 的值加上 2000。  
月份名称和上午或下午指标不区分大小写。

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

`timestamp`

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

```
TO_TIMESTAMP('2007T')                         -- `2007T`
TO_TIMESTAMP('2007-02-23T12:14:33.079-08:00') -- `2007-02-23T12:14:33.079-08:00`
TO_TIMESTAMP('2016', 'y')                     -- `2016T`
TO_TIMESTAMP('2016', 'yyyy')                  -- `2016T`
TO_TIMESTAMP('02-2016', 'MM-yyyy')            -- `2016-02T`
TO_TIMESTAMP('Feb 2016', 'MMM yyyy')          -- `2016-02T`
TO_TIMESTAMP('February 2016', 'MMMM yyyy')     -- `2016-02T`

-- Runnable statements
SELECT TO_TIMESTAMP('2007T') FROM << 0 >>              -- 2007T
SELECT TO_TIMESTAMP('02-2016', 'MM-yyyy') FROM << 0 >> -- 2016-02T
```

## 相关函数
<a name="ql-functions.to_timestamp.related"></a>
+ [CAST](ql-functions.cast.md)
+ [DATE\$1ADD](ql-functions.date_add.md)
+ [DATE\$1DIFF](ql-functions.date_diff.md)
+ [EXTRACT](ql-functions.extract.md)
+ [TO\$1STRING](ql-functions.to_string.md)
+ [UTCNOW](ql-functions.utcnow.md)

# Amazon QLDB 中的 TRIM 功能
<a name="ql-functions.trim"></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 中，使用`TRIM`函数通过删除前导和尾随的空格或*一组*指定的字符来修剪给定字符串。

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

```
TRIM ( [ LEADING | TRAILING | BOTH [ characters ] FROM ] string)
```

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

LEADING  
（可选）表示要从的开头删除空格或指定字符*string*。如果未指定，则默认值为 `BOTH`。

TRAILING  
（可选）表示要从末尾删除空格或指定字符*string*。如果未指定，则默认值为 `BOTH`。

BOTH  
（可选）表示要从的开头和结尾同时删除前导和结尾的*string*空格或指定字符。

*characters*  
（可选）要删除的*字符集*，指定为`string`。  
如未提供此参数，则会删除空格。

*string*  
函数修剪的数据类型 `string` 的字段名称或表达式。

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

`string`

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

```
TRIM('       foobar         ')               -- 'foobar'
TRIM('      \tfoobar\t         ')            -- '\tfoobar\t'
TRIM(LEADING FROM '       foobar         ')  -- 'foobar         '
TRIM(TRAILING FROM '       foobar         ') -- '       foobar'
TRIM(BOTH FROM '       foobar         ')     -- 'foobar'
TRIM(BOTH '1' FROM '11foobar11')             -- 'foobar'
TRIM(BOTH '12' FROM '1112211foobar22211122') -- 'foobar'

-- Runnable statements
SELECT TRIM('       foobar         ') FROM << 0 >>              -- "foobar"
SELECT TRIM(LEADING FROM '       foobar         ') FROM << 0 >> -- "foobar         "
```

## 相关函数
<a name="ql-functions.trim.related"></a>
+ [CHAR\$1LENGTH](ql-functions.char_length.md)
+ [LOWER](ql-functions.lower.md)
+ [SUBSTRING](ql-functions.substring.md)
+ [UPPER](ql-functions.upper.md)

# Amazon QLDB 中的 TXID 函数
<a name="ql-functions.txid"></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 中，使用`TXID`函数返回您正在运行的当前语句的唯一事务 ID。这是将当前事务提交至日志账时分配给文档`txId`元数据字段的值。

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

```
TXID()
```

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

无

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

`string`

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

```
SELECT TXID() FROM << 0 >>  -- "L7S9iJqcn9W2M4qOEn27ay"
SELECT TXID() FROM Person WHERE GovId = 'LEWISR261LL'  -- "BKeMb48PNyvHWJGZHkaodG"
```

# Amazon QLDB 中的 UPPER 函数
<a name="ql-functions.upper"></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 中，使用`UPPER`函数将给定字符串中的所有小写字符转换为大写字符。

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

```
UPPER ( string )
```

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

*string*  
函数转换的数据类型的 `string` 字段名称或表达式。

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

`string`

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

```
SELECT UPPER('AbCdEfG!@#$') FROM << 0 >> -- 'ABCDEFG!@#$'
```

## 相关函数
<a name="ql-functions.upper.related"></a>
+ [CHAR\$1LENGTH](ql-functions.char_length.md)
+ [LOWER](ql-functions.lower.md)
+ [SUBSTRING](ql-functions.substring.md)
+ [TRIM](ql-functions.trim.md)

# Amazon QLDB 中的 UTCNOW 函数
<a name="ql-functions.utcnow"></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 中，使用`UTCNOW`函数将以协调世界时（UTC）表示的当前时间返回为`timestamp`。

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

```
UTCNOW()
```

此函数要求您在 `SELECT`查询中指定`FROM`子句。

## 参数
<a name="ql-functions.utcnow.arguments"></a>

无

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

`timestamp`

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

```
SELECT UTCNOW() FROM << 0 >>  -- 2019-12-27T20:12:16.999Z
SELECT UTCNOW() FROM Person WHERE GovId = 'LEWISR261LL'  -- 2019-12-27T20:12:26.999Z

INSERT INTO Person VALUE { 'firstName': 'Jane', 'createdAt': UTCNOW() }
UPDATE Person p SET p.updatedAt = UTCNOW() WHERE p.firstName = 'John'
```

## 相关函数
<a name="ql-functions.utcnow.related"></a>
+ [DATE\$1ADD](ql-functions.date_add.md)
+ [DATE\$1DIFF](ql-functions.date_diff.md)
+ [EXTRACT](ql-functions.extract.md)
+ [TO\$1STRING](ql-functions.to_string.md)
+ [TO\$1TIMESTAMP](ql-functions.to_timestamp.md)

# 时间戳格式字符串
<a name="ql-functions.timestamp-format"></a>

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

本节提供时间戳格式字符串参考信息。

时间戳格式字符串适用于 `TO_STRING` 和 `TO_TIMESTAMP` 函数。这些字符串可以包含日期部分分隔符（例如 `-`、`/` 或 `:`）和以下格式符号。

[\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/zh_cn/qldb/latest/developerguide/ql-functions.timestamp-format.html)

# Amazon QLDB 中的 Partiql 存储进程
<a name="ql-stored-procedures"></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 中，您可使用`EXEC`命令按照以下语法运行 PartiQL 存储过程。

```
EXEC stored_procedure_name argument [, ... ]
```

QLDB 仅支持以下系统存储过程：

**Topics**
+ [REDACT\$1REVISION](ql-stored-procedures.redact_revision.md)

# Amazon QLDB 中的 REDACT\$1REVISION 存储进程
<a name="ql-stored-procedures.redact_revision"></a>

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

**注意**  
2021 年 7 月 22 日之前创建的任何分类账目前都不符合编校资格。您可在 Amazon QLDB 控制台查看分类账的创建时间。

在 Amazon QLDB 中，使用 `REDACT_REVISION` 存储过程永久删除索引存储和日记账存储中的单个非活动文档修订版。此存储过程将删除指定版本的所有用户数据。但是，它将使日记账序列和文档元数据（包括文档 ID 和哈希）保持不变。*该操作不可逆。*

指定的文档修订版本必须是在历史记录中处于非活动状态的修订版。文档的最新有效修订版不符合此编校条件。

通过运行此存储过程提交编校请求后，QLDB 将异步处理数据的编校。修订完成后，指定修订的用户数据（由 `data` 结构表示）将被新的 `dataHash` 字段替换。该字段的值是已移除 `data` 结构的 [Amazon Ion](ion.md) 哈希。因此，分类账保持了其整体数据的完整性，并通过现有验证 API 操作保持加密可验证性。

有关使用示例数据编校操作的示例，请参见[对文档修订版执行编校](working.redaction.md)中的[编校示例](working.redaction.md#working.redaction.example)。

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

**Topics**
+ [修订注意事项和限制](#ql-stored-procedures.redact_revision.considerations)
+ [语法](#ql-stored-procedures.redact_revision.syntax)
+ [Arguments](#ql-stored-procedures.redact_revision.arguments)
+ [返回值](#ql-stored-procedures.redact_revision.return)
+ [示例](#ql-stored-procedures.redact_revision.examples)

## 修订注意事项和限制
<a name="ql-stored-procedures.redact_revision.considerations"></a>

开始在 Amazon QLDB 中进行数据编校之前，请务必查看以下注意事项和限制：
+ `REDACT_REVISION` 存储过程以单个非活动文档修订版中的用户数据为目标。若要编校多个修订版，必须为每个修订版运行一次存储进程。您可为每笔事务编校一个修订版。
+ 若要编校文档修订版中的特定字段，必须先使用单独的数据操作语言（DML）语句修改修订版。有关更多信息，请参阅 [编校修订版本中的特定字段](working.redaction.md#working.redaction.field)。
+ QLDB 收到编校请求后，您将无法取消或更改该请求。若要确认编校是否已完成，您可以检查修订的`data`结构是否已被`dataHash`字段所取代。要了解更多信息，请参阅 [检查编校是否已完成](working.redaction.md#working.redaction.check-completion)。
+ 编校对 QLDB 服务之外复制的任何 QLDB 数据没有影响。这包括 Amazon S3 的任何导出以及 Amazon Kinesis Data Streams 的任何导出。您必须使用其他数据保留方法管理存储在 QLDB 之外的任何数据。
+ 编校对日记账中记录的 PartiQL 语句的文字值没有影响。根据最佳实践标准，您应使用变量占位符而非文字值，以编程方式运行参数化语句。占位符以问号（`?`）的形式写在日记账内，而不是任何可能需要编校的敏感信息。

  若要了解如何使用 QLDB 驱动程序以编程方式运行 PartiQL 语句，请参阅[驱动程序入门](getting-started-driver.md)中每种支持的编程语言的教程。

## 语法
<a name="ql-stored-procedures.redact_revision.syntax"></a>

```
EXEC REDACT_REVISION `block-address`, 'table-id', 'document-id'
```

## Arguments
<a name="ql-stored-procedures.redact_revision.arguments"></a>

`*block-address*`  
要编校的文档修订版本的日记账数据块位置。地址是一种包含两个字段的 Amazon Ion 结构：`strandId` 和 `sequenceNo`。  
这是一个 Ion 字面值，以反引号表示。例如：  

```
`{strandId:"JdxjkR9bSYB5jMHWcI464T", sequenceNo:17}`
```
要了解如何查找数据块地址，请参阅 [查询文档元数据](working.metadata.md)。

'*table-id*'  
待编校修订版本的表的唯一 ID，用单引号表示。  
若要了解如何查找表 ID，请参阅 [查询系统目录](working.catalog.md)。

'*document-id*'  
待编校修订版本的唯一文档 ID，用单引号表示。  
若要了解如何查找文档 ID，请参阅 [查询文档元数据](working.metadata.md)。

## 返回值
<a name="ql-stored-procedures.redact_revision.return"></a>

表示要编校文档修订版的 Amazon Ion 结构，格式如下。

```
{
  blockAddress: {
    strandId: String,
    sequenceNo: Int
  },
  tableId: String,
  documentId: String,
  version: Int
}
```

**返回结构字段**
+ `blockAddress` — 要编校的修订版本的日记账数据块位置。地址包含以下两个字段。
  + `strandId` — 包含数据块的日记账链的唯一 ID。
  + `sequenceNo` — 一个索引号，用于指定数据块在链中的位置。
+ `tableId` — 您正在编校其修订版本的表的唯一 ID。
+ `documentId` — 要编校的修订版本的唯一文档 ID。
+ `version` — 要编校的文档修订版的版本号。

下面是含采样数据的返回结构示例。

```
{
  blockAddress: {
    strandId: "CsRnx0RDoNK6ANEEePa1ov",
    sequenceNo: 134
  },
  tableId: "6GZumdHggklLdMGyQq9DNX",
  documentId: "IXlQPSbfyKMIIsygePeKrZ",
  version: 0
}
```

## 示例
<a name="ql-stored-procedures.redact_revision.examples"></a>

```
EXEC REDACT_REVISION `{strandId:"7z2P0AyQKWD8oFYmGNhi8D", sequenceNo:7}`, '8F0TPCmdNQ6JTRpiLj2TmW', '05K8zpGYWynDlEOK5afDRc'
```

# Amazon QLDB 中的 PartiQL 运算符
<a name="ql-operators"></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 支持以下 [SQL 标准运算符](https://www.w3schools.com/sql/sql_operators.asp)。

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

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


****  

| 运算符 | 描述 | 
| --- | --- | 
| \$1 | 添加 | 
| - | Subtract | 
| \$1 | Multiply | 
| / | Divide | 
| % | 取模 | 

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


****  

| 运算符 | 描述 | 
| --- | --- | 
| = | 等于 | 
| > | Greater than | 
| < | Less than | 
| >= | 大于或等于 | 
| <= | 小于或等于 | 
| <> | 不等于 | 

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


****  

| 运算符 | 描述 | 
| --- | --- | 
| AND | 如果 AND 分隔的所有条件都为 TRUE，则为 TRUE | 
| BETWEEN | 如果运算数在比较范围内，则为 TRUE | 
| IN | 如果运算数等于表达式列表中的一个，则为 TRUE | 
| IS | TRUE如果运算数是给定的数据类型，包括 NULL 和 MISSING | 
| LIKE | 如果操作数与模式匹配，则为 TRUE | 
| NOT | 反转给定布尔表达式的值 | 
| OR | TRUE如果 OR 分隔的任意条件为 TRUE | 

## 字符串运算符
<a name="ql-operators.compound"></a>


****  

| 运算符 | 描述 | 
| --- | --- | 
| \$1\$1 | 联接位于 \$1\$1 符号的任意一侧的两个字符串并返回联接后的字符串。如果一个或两个表达式都为 NULL，则联接的结果为空。 | 

# Amazon QLDB 中的保留关键词
<a name="ql-reference.reserved"></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 保留关键字的列表。您可以使用保留关键字作为带双引号的标识符（例如`"user"`）。有关 QLDB 中 PartiQL 引用惯例的信息，请参阅[使用 PartiQL 查询 Ion](ql-reference.query.md)。

**重要**  
[此列表中的关键字都被视为保留关键词，因为 PartiQL 与 SQL-92 向后兼容。](http://www.contrib.andrew.cmu.edu/~shadow/sql/sql1992.txt)但是，QLDB 仅支持这些保留字子集。有关 QLDB 当前支持的 SQL 关键字列表，请参见以下主题：  
[PartiQL 函数](ql-functions.md)
[PartiQL 运算符](ql-operators.md)
[PartiQL 命令](ql-reference.statements.md)

```
ABSOLUTE
ACTION
ADD
ALL
ALLOCATE
ALTER
AND
ANY
ARE
AS
ASC
ASSERTION
AT
AUTHORIZATION
AVG
BAG
BEGIN
BETWEEN
BIT
BIT_LENGTH
BLOB
BOOL
BOOLEAN
BOTH
BY
CASCADE
CASCADED
CASE
CAST
CATALOG
CHAR
CHARACTER
CHARACTER_LENGTH
CHAR_LENGTH
CHECK
CLOB
CLOSE
COALESCE
COLLATE
COLLATION
COLUMN
COMMIT
CONNECT
CONNECTION
CONSTRAINT
CONSTRAINTS
CONTINUE
CONVERT
CORRESPONDING
COUNT
CREATE
CROSS
CURRENT
CURRENT_DATE
CURRENT_TIME
CURRENT_TIMESTAMP
CURRENT_USER
CURSOR
DATE
DATE_ADD
DATE_DIFF
DAY
DEALLOCATE
DEC
DECIMAL
DECLARE
DEFAULT
DEFERRABLE
DEFERRED
DELETE
DESC
DESCRIBE
DESCRIPTOR
DIAGNOSTICS
DISCONNECT
DISTINCT
DOMAIN
DOUBLE
DROP
ELSE
END
END-EXEC
ESCAPE
EXCEPT
EXCEPTION
EXEC
EXECUTE
EXISTS
EXTERNAL
EXTRACT
FALSE
FETCH
FIRST
FLOAT
FOR
FOREIGN
FOUND
FROM
FULL
GET
GLOBAL
GO
GOTO
GRANT
GROUP
HAVING
HOUR
IDENTITY
IMMEDIATE
IN
INDEX
INDICATOR
INITIALLY
INNER
INPUT
INSENSITIVE
INSERT
INT
INTEGER
INTERSECT
INTERVAL
INTO
IS
ISOLATION
JOIN
KEY
LANGUAGE
LAST
LEADING
LEFT
LEVEL
LIKE
LIMIT
LIST
LOCAL
LOWER
MATCH
MAX
MIN
MINUTE
MISSING
MODULE
MONTH
NAMES
NATIONAL
NATURAL
NCHAR
NEXT
NO
NOT
NULL
NULLIF
NUMERIC
OCTET_LENGTH
OF
ON
ONLY
OPEN
OPTION
OR
ORDER
OUTER
OUTPUT
OVERLAPS
PAD
PARTIAL
PIVOT
POSITION
PRECISION
PREPARE
PRESERVE
PRIMARY
PRIOR
PRIVILEGES
PROCEDURE
PUBLIC
READ
REAL
REFERENCES
RELATIVE
REMOVE
RESTRICT
REVOKE
RIGHT
ROLLBACK
ROWS
SCHEMA
SCROLL
SECOND
SECTION
SELECT
SESSION
SESSION_USER
SET
SEXP
SIZE
SMALLINT
SOME
SPACE
SQL
SQLCODE
SQLERROR
SQLSTATE
STRING
STRUCT
SUBSTRING
SUM
SYMBOL
SYSTEM_USER
TABLE
TEMPORARY
THEN
TIME
TIMESTAMP
TIMEZONE_HOUR
TIMEZONE_MINUTE
TO
TO_STRING
TO_TIMESTAMP
TRAILING
TRANSACTION
TRANSLATE
TRANSLATION
TRIM
TRUE
TUPLE
TXID
UNDROP
UNION
UNIQUE
UNKNOWN
UNPIVOT
UPDATE
UPPER
USAGE
USER
USING
UTCNOW
VALUE
VALUES
VARCHAR
VARYING
VIEW
WHEN
WHENEVER
WHERE
WITH
WORK
WRITE
YEAR
ZONE
```

# Amazon QLDB 中的 Amazon Ion 数据格式参考
<a name="ion"></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 使用一种数据表示法模型，该模型将 [Amazon Ion](http://amzn.github.io/ion-docs/) 与一部分 PartiQL](https://partiql.org/)类型的子集统一起来。本节提供了 Ion 文档数据格式的参考概述，其与 PartiQL 的集成是分开的。

**在 Amazon QLDB 中使用 PartiQL 查询 Ion**

有关在 QLDB 中使用 PartiQL 查询 Ion 数据的语法和语义，请参阅 *Amazon QLDB PartiQL 参考*中的[使用 PartiQL 查询 Ion](ql-reference.query.md)。

有关在 QLDB 分类账中查询和处理 Ion 数据的代码示例，请参阅和[Amazon Ion 代码示例](ion.code-examples.md)和 [使用 Amazon Ion](driver-working-with-ion.md)。

**Topics**
+ [什么是 Amazon Ion？](#ion.summary)
+ [Ion 规格](#ion.spec)
+ [兼容 JSON](#ion.json-compatible)
+ [JSON 扩展](#ion.json-ext)
+ [Ion 文本示例](#ion.example)
+ [API 参考](#ion.api-ref)
+ [QLDB 中的 Amazon Ion 代码示例](ion.code-examples.md)

## 什么是 Amazon Ion？
<a name="ion.summary"></a>

Ion 是一种开源、类型丰富、自我描述的分层数据序列化格式，最初由 Amazon 内部开发。它基于抽象数据模型，允许您存储结构化和非结构化数据。它是 JSON 的超集，这意味着任何有效的 JSON 文档也是有效的 Ion 文档。本指南假设有 JSON 的基准理论。如果您还不熟悉 JSON，请参阅 [JSON 简介](http://json.org)了解更多信息。

你可以用人类可读的文本形式或二进制编码的形式交替标注 Ion 文档。与 JSON 一样，文本表单易于读写，支持快速原型设计。二进制编码在保存、传输和解析方面更紧凑和高效。离子处理器可在两种格式之间进行转码，以表示完全相同的数据结构集，而不会丢失任何数据。此功能允许应用程序针对不同的用例优化其数据处理方式。

**注意**  
Ion 数据模型严格基于值，不支持引用。因此，数据模型可以表示可以嵌套至任意深度的数据层次结构，但不能表示有向图。

## Ion 规格
<a name="ion.spec"></a>

有关 Ion core 数据类型的完整列表以及完整描述和值格式化细节，请参阅 Amazon GitHub 网站上的 [Ion 规范文档](http://amzn.github.io/ion-docs/docs/spec.html)。

为了简化应用程序开发，Amazon Ion 提供了可处理 Ion 数据的客户端库。有关处理 Ion 数据的常见用例的代码示例，请参阅上 GitHub的 [Amazon Ion Cookbook](http://amzn.github.io/ion-docs/guides/cookbook.html)。

## 兼容 JSON
<a name="ion.json-compatible"></a>

与 JSON 类似的是，您可以使用一组原始数据类型和一组递归定义的容器类型编写 Amazon Ion 文档。Ion 包含以下传统 JSON 数据类型：
+ `null`: 一个通用的非类型空值（空）。此外，如下一节所述，Ion 支持每种基元类型使用不同的空类型。
+ `bool`: 布尔值。
+ `string`：Unicode 文本文字。
+ `list`：有序的异构值集合。
+ `struct`：名称/值对的无序集合。与 JSON 一样，`struct`允许每个名称有多个值，但通常不鼓励这样操作。

## JSON 扩展
<a name="ion.json-ext"></a>



### 数字类型
<a name="ion.json-ext.numbers"></a>

Amazon Ion 将数字严格定义为以下`number`类型之一，而非模棱两可的 JSON 类型：
+ `int`：任意大小的有符号整数。
+ `decimal`：任意精度的十进制编码实数。
+ `float`：二进制编码的浮点数（64 位 IEEE）。

解析文档时，Ion 处理器会按以下方式分配数字类型：
+ `int`：带有小数点但没有指数的数字（例如，`100200`）。
+ `decimal`: 没有指数或小数点的数字（例如，`0.00001`、`200.0`）。
+ `float`: 带指数的数字，例如科学记数法或 E 记数法（例如`2e0`、`3.1e-4`）。

### 新数据类型
<a name="ion.json-ext.newtypes"></a>

Amazon Ion 添加了以下数据类型：
+ `timestamp`: 任意精确Date/time/timezone的时刻。
+ `symbol`：Unicode 符号原子（例如标识符）。
+ `blob`：用户定义编码的二进制数据。
+ `clob`：用户定义编码的文本数据。
+ `sexp`：具有应用程序定义语义的有序值集合。

### Null 类型
<a name="ion.json-ext.nulls"></a>

除了 JSON 定义的通用空类型外，Amazon Ion 还支持每种原始类型使用不同的空类型。这表明在保持严格的数据类型的同时缺乏价值。

```
null
null.null       // Identical to untyped null
null.bool
null.int
null.float
null.decimal
null.timestamp
null.string
null.symbol
null.blob
null.clob
null.struct
null.list
null.sexp
```

## Ion 文本示例
<a name="ion.example"></a>

```
// Here is a struct, which is similar to a JSON object.
{
    // Field names don't always have to be quoted.
    name: "fido",
    
    // This is an integer.
    age: 7,
    
    // This is a timestamp with day precision.
    birthday: 2012-03-01T,
    
    // Here is a list, which is like a JSON array.
    toys: [
        // These are symbol values, which are like strings,
        // but get encoded as integers in binary.
        ball,
        rope
    ],
}
```

## API 参考
<a name="ion.api-ref"></a>
+ [ion-go](https://pkg.go.dev/github.com/amzn/ion-go/ion)
+ [ion-java](https://www.javadoc.io/doc/com.amazon.ion/ion-java/latest/index.html)
+ [ion-js](https://amazon-ion.github.io/ion-js/api/)
+ [ion-python](https://ion-python.readthedocs.io/en/latest/)

# QLDB 中的 Amazon Ion 代码示例
<a name="ion.code-examples"></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 分类账中读取和写入文档值处理 Amazon Ion 数据的代码示例。代码示例使用 QLDB 驱动程序在分类账运行 PartiQL 语句。这些示例是示例应用程序的一部分[使用示例应用程序教程，开始使用 Amazon QLDB](getting-started-sample-app.md)，在 Samples [ GitHub 网站上](https://github.com/aws-samples/?q=qldb)是开源的。AWS 

有关显示处理 Ion 数据的常见用例的通用代码示例，请参阅上 GitHub的 [Amazon Ion Cookbook](http://amzn.github.io/ion-docs/guides/cookbook.html)。

## 运行代码
<a name="ion.code-examples.running"></a>

每种编程语言的教程代码都可执行以下步骤：

1. 连接至 `vehicle-registration` 示例分类账。

1. 创建名为 `IonTypes` 的文件。

1. 在表格中插入包含单个 `Name` 字段的文档。

1. 对于每种支持的[Ion 数据类型](http://amzn.github.io/ion-docs/docs/spec.html)：

   1. 使用该数据类型的文字值更新文档的`Name`字段。

   1. 查询表格以获取文档最新版本。

   1. 通过检查的值是否与预期的类型相匹配，验证其值是否保留`Name`了其原始数据类型属性。

1. 删除 `IonTypes`表。

**注意**  
运行本教程代码之前，您必须创建一个名为的分类账`vehicle-registration`。

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

```
/*
 * Copyright 2019 Amazon.com, Inc. or its affiliates. All Rights Reserved.
 * SPDX-License-Identifier: MIT-0
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy of this
 * software and associated documentation files (the "Software"), to deal in the Software
 * without restriction, including without limitation the rights to use, copy, modify,
 * merge, publish, distribute, sublicense, and/or sell copies of the Software, and to
 * permit persons to whom the Software is furnished to do so.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
 * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
 * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
 * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
 * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 */

package software.amazon.qldb.tutorial;

import com.amazon.ion.IonBlob;
import com.amazon.ion.IonBool;
import com.amazon.ion.IonClob;
import com.amazon.ion.IonDecimal;
import com.amazon.ion.IonFloat;
import com.amazon.ion.IonInt;
import com.amazon.ion.IonList;
import com.amazon.ion.IonNull;
import com.amazon.ion.IonSexp;
import com.amazon.ion.IonString;
import com.amazon.ion.IonStruct;
import com.amazon.ion.IonSymbol;
import com.amazon.ion.IonTimestamp;
import com.amazon.ion.IonValue;
import com.amazon.ion.Timestamp;
import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonProperty;
import java.util.Collections;
import java.util.List;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import software.amazon.qldb.Result;
import software.amazon.qldb.TransactionExecutor;

/**
 * Insert all the supported Ion types into a ledger and verify that they are stored and can be retrieved properly, retaining
 * their original properties.
 *
 * This code expects that you have AWS credentials setup per:
 * http://docs.aws.amazon.com/java-sdk/latest/developer-guide/setup-credentials.html
 */
public class InsertIonTypes {
    public static final Logger log = LoggerFactory.getLogger(InsertIonTypes.class);
    public static final String TABLE_NAME = "IonTypes";

    private InsertIonTypes() {}

    /**
     * Update a document's Name value in the database. Then, query the value of the Name key and verify the expected Ion type was
     * saved.
     *
     * @param txn
     *              The {@link TransactionExecutor} for statement execution.
     * @param ionValue
     *              The {@link IonValue} to set the document's Name value to.
     *
     * @throws AssertionError when no value is returned for the Name key or if the value does not match the expected type.
     */
    public static void updateRecordAndVerifyType(final TransactionExecutor txn, final IonValue ionValue) {
        final String updateStatement = String.format("UPDATE %s SET Name = ?", TABLE_NAME);
        final List<IonValue> parameters = Collections.singletonList(ionValue);
        txn.execute(updateStatement, parameters);
        log.info("Updated document.");

        final String searchQuery = String.format("SELECT VALUE Name FROM %s", TABLE_NAME);
        final Result result = txn.execute(searchQuery);

        if (result.isEmpty()) {
            throw new AssertionError("Did not find any values for the Name key.");
        }
        for (IonValue value : result) {
            if (!ionValue.getClass().isInstance(value)) {
                throw new AssertionError(String.format("The queried value, %s, is not an instance of %s.",
                        value.getClass().toString(), ionValue.getClass().toString()));
            }
            if (!value.getType().equals(ionValue.getType())) {
                throw new AssertionError(String.format("The queried value type, %s, does not match %s.",
                        value.getType().toString(), ionValue.getType().toString()));
            }
        }

        log.info("Successfully verified value is instance of {} with type {}.", ionValue.getClass().toString(),
                ionValue.getType().toString());
    }

    /**
     * Delete a table.
     *
     * @param txn
     *              The {@link TransactionExecutor} for lambda execute.
     * @param tableName
     *              The name of the table to delete.
     */
    public static void deleteTable(final TransactionExecutor txn, final String tableName) {
        log.info("Deleting {} table...", tableName);
        final String statement = String.format("DROP TABLE %s", tableName);
        txn.execute(statement);
        log.info("{} table successfully deleted.", tableName);
    }

    public static void main(final String... args) {
        final IonBlob ionBlob = Constants.SYSTEM.newBlob("hello".getBytes());
        final IonBool ionBool = Constants.SYSTEM.newBool(true);
        final IonClob ionClob = Constants.SYSTEM.newClob("{{'This is a CLOB of text.'}}".getBytes());
        final IonDecimal ionDecimal = Constants.SYSTEM.newDecimal(0.1);
        final IonFloat ionFloat = Constants.SYSTEM.newFloat(0.2);
        final IonInt ionInt = Constants.SYSTEM.newInt(1);
        final IonList ionList = Constants.SYSTEM.newList(new int[]{1, 2});
        final IonNull ionNull = Constants.SYSTEM.newNull();
        final IonSexp ionSexp = Constants.SYSTEM.newSexp(new int[]{2, 3});
        final IonString ionString = Constants.SYSTEM.newString("string");
        final IonStruct ionStruct = Constants.SYSTEM.newEmptyStruct();
        ionStruct.put("brand", Constants.SYSTEM.newString("ford"));
        final IonSymbol ionSymbol = Constants.SYSTEM.newSymbol("abc");
        final IonTimestamp ionTimestamp = Constants.SYSTEM.newTimestamp(Timestamp.now());

        final IonBlob ionNullBlob = Constants.SYSTEM.newNullBlob();
        final IonBool ionNullBool = Constants.SYSTEM.newNullBool();
        final IonClob ionNullClob = Constants.SYSTEM.newNullClob();
        final IonDecimal ionNullDecimal = Constants.SYSTEM.newNullDecimal();
        final IonFloat ionNullFloat = Constants.SYSTEM.newNullFloat();
        final IonInt ionNullInt = Constants.SYSTEM.newNullInt();
        final IonList ionNullList = Constants.SYSTEM.newNullList();
        final IonSexp ionNullSexp = Constants.SYSTEM.newNullSexp();
        final IonString ionNullString = Constants.SYSTEM.newNullString();
        final IonStruct ionNullStruct = Constants.SYSTEM.newNullStruct();
        final IonSymbol ionNullSymbol = Constants.SYSTEM.newNullSymbol();
        final IonTimestamp ionNullTimestamp = Constants.SYSTEM.newNullTimestamp();


        ConnectToLedger.getDriver().execute(txn -> {
            CreateTable.createTable(txn, TABLE_NAME);
            final Document document = new Document(Constants.SYSTEM.newString("val"));
            InsertDocument.insertDocuments(txn, TABLE_NAME, Collections.singletonList(document));

            updateRecordAndVerifyType(txn, ionBlob);
            updateRecordAndVerifyType(txn, ionBool);
            updateRecordAndVerifyType(txn, ionClob);
            updateRecordAndVerifyType(txn, ionDecimal);
            updateRecordAndVerifyType(txn, ionFloat);
            updateRecordAndVerifyType(txn, ionInt);
            updateRecordAndVerifyType(txn, ionList);
            updateRecordAndVerifyType(txn, ionNull);
            updateRecordAndVerifyType(txn, ionSexp);
            updateRecordAndVerifyType(txn, ionString);
            updateRecordAndVerifyType(txn, ionStruct);
            updateRecordAndVerifyType(txn, ionSymbol);
            updateRecordAndVerifyType(txn, ionTimestamp);

            updateRecordAndVerifyType(txn, ionNullBlob);
            updateRecordAndVerifyType(txn, ionNullBool);
            updateRecordAndVerifyType(txn, ionNullClob);
            updateRecordAndVerifyType(txn, ionNullDecimal);
            updateRecordAndVerifyType(txn, ionNullFloat);
            updateRecordAndVerifyType(txn, ionNullInt);
            updateRecordAndVerifyType(txn, ionNullList);
            updateRecordAndVerifyType(txn, ionNullSexp);
            updateRecordAndVerifyType(txn, ionNullString);
            updateRecordAndVerifyType(txn, ionNullStruct);
            updateRecordAndVerifyType(txn, ionNullSymbol);
            updateRecordAndVerifyType(txn, ionNullTimestamp);

            deleteTable(txn, TABLE_NAME);
        });
    }

    /**
     * This class represents a simple document with a single key, Name, to use for the IonTypes table.
     */
    private static class Document {
        private final IonValue name;

        @JsonCreator
        private Document(@JsonProperty("Name") final IonValue name) {
            this.name = name;
        }

        @JsonProperty("Name")
        private IonValue getName() {
            return name;
        }
    }
}
```

------
#### [ Node.js ]

```
/*
 * Copyright 2019 Amazon.com, Inc. or its affiliates. All Rights Reserved.
 * SPDX-License-Identifier: MIT-0
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy of this
 * software and associated documentation files (the "Software"), to deal in the Software
 * without restriction, including without limitation the rights to use, copy, modify,
 * merge, publish, distribute, sublicense, and/or sell copies of the Software, and to
 * permit persons to whom the Software is furnished to do so.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
 * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
 * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
 * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
 * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 */

import { QldbDriver, Result, TransactionExecutor } from "amazon-qldb-driver-nodejs";
import { AssertionError } from "assert";
import { dom, IonType, IonTypes } from "ion-js";

import { insertDocument } from "./InsertDocument";
import { getQldbDriver } from "./ConnectToLedger";
import { createTable } from "./CreateTable";
import { error, log } from "./qldb/LogUtil";

const TABLE_NAME: string = "IonTypes";

/**
 * Delete a table.
 * @param txn The {@linkcode TransactionExecutor} for lambda execute.
 * @param tableName Name of the table to delete.
 * @returns Promise which fulfills with void.
 */
export async function deleteTable(txn: TransactionExecutor, tableName: string): Promise<void> {
    log(`Deleting ${tableName} table...`);
    const statement: string = `DROP TABLE ${tableName}`;
    await txn.execute(statement);
    log(`${tableName} table successfully deleted.`);
}

/**
 * Update a document's Name value in QLDB. Then, query the value of the Name key and verify the expected Ion type was
 * saved.
 * @param txn The {@linkcode TransactionExecutor} for lambda execute.
 * @param parameter The IonValue to set the document's Name value to.
 * @param ionType The Ion type that the Name value should be.
 * @returns Promise which fulfills with void.
 */
async function updateRecordAndVerifyType(
    txn: TransactionExecutor,
    parameter: any,
    ionType: IonType
): Promise<void> {
    const updateStatement: string = `UPDATE ${TABLE_NAME} SET Name = ?`;
    await txn.execute(updateStatement, parameter);
    log("Updated record.");

    const searchStatement: string = `SELECT VALUE Name FROM ${TABLE_NAME}`;
    const result: Result = await txn.execute(searchStatement);

    const results: dom.Value[] = result.getResultList();

    if (0 === results.length) {
        throw new AssertionError({
            message: "Did not find any values for the Name key."
        });
    }

    results.forEach((value: dom.Value) => {
        if (value.getType().binaryTypeId !== ionType.binaryTypeId) {
            throw new AssertionError({
                message: `The queried value type, ${value.getType().name}, does not match expected type, ${ionType.name}.`
            });
        }
    });

    log(`Successfully verified value is of type ${ionType.name}.`);
}

/**
 * Insert all the supported Ion types into a table and verify that they are stored and can be retrieved properly,
 * retaining their original properties.
 * @returns Promise which fulfills with void.
 */
const main = async function(): Promise<void> {
    try {
        const qldbDriver: QldbDriver = getQldbDriver();
        await qldbDriver.executeLambda(async (txn: TransactionExecutor) => {
            await createTable(txn, TABLE_NAME);
            await insertDocument(txn, TABLE_NAME, [{ "Name": "val" }]);
            await updateRecordAndVerifyType(txn, dom.load("null"), IonTypes.NULL);
            await updateRecordAndVerifyType(txn, true, IonTypes.BOOL);
            await updateRecordAndVerifyType(txn, 1, IonTypes.INT);
            await updateRecordAndVerifyType(txn, 3.2, IonTypes.FLOAT);
            await updateRecordAndVerifyType(txn, dom.load("5.5"), IonTypes.DECIMAL);
            await updateRecordAndVerifyType(txn, dom.load("2020-02-02"), IonTypes.TIMESTAMP);
            await updateRecordAndVerifyType(txn, dom.load("abc123"), IonTypes.SYMBOL);
            await updateRecordAndVerifyType(txn, dom.load("\"string\""), IonTypes.STRING);
            await updateRecordAndVerifyType(txn, dom.load("{{ \"clob\" }}"), IonTypes.CLOB);
            await updateRecordAndVerifyType(txn, dom.load("{{ blob }}"), IonTypes.BLOB);
            await updateRecordAndVerifyType(txn, dom.load("(1 2 3)"), IonTypes.SEXP);
            await updateRecordAndVerifyType(txn, dom.load("[1, 2, 3]"), IonTypes.LIST);
            await updateRecordAndVerifyType(txn, dom.load("{brand: ford}"), IonTypes.STRUCT);
            await deleteTable(txn, TABLE_NAME);
        });
    } catch (e) {
        error(`Error updating and validating Ion types: ${e}`);
    }
}

if (require.main === module) {
    main();
}
```

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

```
# Copyright 2019 Amazon.com, Inc. or its affiliates. All Rights Reserved.
# SPDX-License-Identifier: MIT-0
#
# Permission is hereby granted, free of charge, to any person obtaining a copy of this
# software and associated documentation files (the "Software"), to deal in the Software
# without restriction, including without limitation the rights to use, copy, modify,
# merge, publish, distribute, sublicense, and/or sell copies of the Software, and to
# permit persons to whom the Software is furnished to do so.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
# INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
# PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
# HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
# SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#
# This code expects that you have AWS credentials setup per:
# https://boto3.amazonaws.com/v1/documentation/api/latest/guide/quickstart.html
from datetime import datetime
from decimal import Decimal
from logging import basicConfig, getLogger, INFO

from amazon.ion.simple_types import IonPyBool, IonPyBytes, IonPyDecimal, IonPyDict, IonPyFloat, IonPyInt, IonPyList, \
    IonPyNull, IonPySymbol, IonPyText, IonPyTimestamp
from amazon.ion.simpleion import loads
from amazon.ion.symbols import SymbolToken
from amazon.ion.core import IonType

from pyqldbsamples.create_table import create_table
from pyqldbsamples.constants import Constants
from pyqldbsamples.insert_document import insert_documents
from pyqldbsamples.model.sample_data import convert_object_to_ion
from pyqldbsamples.connect_to_ledger import create_qldb_driver

logger = getLogger(__name__)
basicConfig(level=INFO)

TABLE_NAME = 'IonTypes'


def update_record_and_verify_type(driver, parameter, ion_object, ion_type):
    """
    Update a record in the database table. Then query the value of the record and verify correct ion type saved.

    :type driver: :py:class:`pyqldb.driver.qldb_driver.QldbDriver`
    :param driver: An instance of the QldbDriver class.

    :type parameter: :py:class:`amazon.ion.simple_types.IonPyValue`
    :param parameter: The Ion value or Python native type that is convertible to Ion for filling in parameters of the
                      statement.

    :type ion_object: :py:obj:`IonPyBool`/:py:obj:`IonPyBytes`/:py:obj:`IonPyDecimal`/:py:obj:`IonPyDict`
                      /:py:obj:`IonPyFloat`/:py:obj:`IonPyInt`/:py:obj:`IonPyList`/:py:obj:`IonPyNull`
                      /:py:obj:`IonPySymbol`/:py:obj:`IonPyText`/:py:obj:`IonPyTimestamp`
    :param ion_object: The Ion object to verify against.

    :type ion_type: :py:class:`amazon.ion.core.IonType`
    :param ion_type: The Ion type to verify against.

    :raises TypeError: When queried value is not an instance of Ion type.
    """
    update_query = 'UPDATE {} SET Name = ?'.format(TABLE_NAME)
    driver.execute_lambda(lambda executor: executor.execute_statement(update_query, parameter))
    logger.info('Updated record.')

    search_query = 'SELECT VALUE Name FROM {}'.format(TABLE_NAME)
    cursor = driver.execute_lambda(lambda executor: executor.execute_statement(search_query))

    for c in cursor:
        if not isinstance(c, ion_object):
            raise TypeError('The queried value is not an instance of {}'.format(ion_object.__name__))

        if c.ion_type is not ion_type:
            raise TypeError('The queried value type does not match {}'.format(ion_type))

    logger.info("Successfully verified value is instance of '{}' with type '{}'.".format(ion_object.__name__, ion_type))
    return cursor


def delete_table(driver, table_name):
    """
    Delete a table.

    :type driver: :py:class:`pyqldb.driver.qldb_driver.QldbDriver`
    :param driver: An instance of the QldbDriver class.

    :type table_name: str
    :param table_name: Name of the table to delete.

    :rtype: int
    :return: The number of changes to the database.
    """
    logger.info("Deleting '{}' table...".format(table_name))
    cursor = driver.execute_lambda(lambda executor: executor.execute_statement('DROP TABLE {}'.format(table_name)))
    logger.info("'{}' table successfully deleted.".format(table_name))
    return len(list(cursor))


def insert_and_verify_ion_types(driver):
    """
    Insert all the supported Ion types and Python values that are convertible to Ion into a ledger and verify that they
    are stored and can be retrieved properly, retaining their original properties.

    :type driver: :py:class:`pyqldb.driver.qldb_driver.QldbDriver`
    :param driver: A QLDB Driver object.
    """
    python_bytes = str.encode('hello')
    python_bool = True
    python_float = float('0.2')
    python_decimal = Decimal('0.1')
    python_string = "string"
    python_int = 1
    python_null = None
    python_datetime = datetime(2016, 12, 20, 5, 23, 43)
    python_list = [1, 2]
    python_dict = {"brand": "Ford"}

    ion_clob = convert_object_to_ion(loads('{{"This is a CLOB of text."}}'))
    ion_blob = convert_object_to_ion(python_bytes)
    ion_bool = convert_object_to_ion(python_bool)
    ion_decimal = convert_object_to_ion(python_decimal)
    ion_float = convert_object_to_ion(python_float)
    ion_int = convert_object_to_ion(python_int)
    ion_list = convert_object_to_ion(python_list)
    ion_null = convert_object_to_ion(python_null)
    ion_sexp = convert_object_to_ion(loads('(cons 1 2)'))
    ion_string = convert_object_to_ion(python_string)
    ion_struct = convert_object_to_ion(python_dict)
    ion_symbol = convert_object_to_ion(SymbolToken(text='abc', sid=123))
    ion_timestamp = convert_object_to_ion(python_datetime)

    ion_null_clob = convert_object_to_ion(loads('null.clob'))
    ion_null_blob = convert_object_to_ion(loads('null.blob'))
    ion_null_bool = convert_object_to_ion(loads('null.bool'))
    ion_null_decimal = convert_object_to_ion(loads('null.decimal'))
    ion_null_float = convert_object_to_ion(loads('null.float'))
    ion_null_int = convert_object_to_ion(loads('null.int'))
    ion_null_list = convert_object_to_ion(loads('null.list'))
    ion_null_sexp = convert_object_to_ion(loads('null.sexp'))
    ion_null_string = convert_object_to_ion(loads('null.string'))
    ion_null_struct = convert_object_to_ion(loads('null.struct'))
    ion_null_symbol = convert_object_to_ion(loads('null.symbol'))
    ion_null_timestamp = convert_object_to_ion(loads('null.timestamp'))

    create_table(driver, TABLE_NAME)
    insert_documents(driver, TABLE_NAME, [{'Name': 'val'}])
    update_record_and_verify_type(driver, python_bytes, IonPyBytes, IonType.BLOB)
    update_record_and_verify_type(driver, python_bool, IonPyBool, IonType.BOOL)
    update_record_and_verify_type(driver, python_float, IonPyFloat, IonType.FLOAT)
    update_record_and_verify_type(driver, python_decimal, IonPyDecimal, IonType.DECIMAL)
    update_record_and_verify_type(driver, python_string, IonPyText, IonType.STRING)
    update_record_and_verify_type(driver, python_int, IonPyInt, IonType.INT)
    update_record_and_verify_type(driver, python_null, IonPyNull, IonType.NULL)
    update_record_and_verify_type(driver, python_datetime, IonPyTimestamp, IonType.TIMESTAMP)
    update_record_and_verify_type(driver, python_list, IonPyList, IonType.LIST)
    update_record_and_verify_type(driver, python_dict, IonPyDict, IonType.STRUCT)
    update_record_and_verify_type(driver, ion_clob, IonPyBytes, IonType.CLOB)
    update_record_and_verify_type(driver, ion_blob, IonPyBytes, IonType.BLOB)
    update_record_and_verify_type(driver, ion_bool, IonPyBool, IonType.BOOL)
    update_record_and_verify_type(driver, ion_decimal, IonPyDecimal, IonType.DECIMAL)
    update_record_and_verify_type(driver, ion_float, IonPyFloat, IonType.FLOAT)
    update_record_and_verify_type(driver, ion_int, IonPyInt, IonType.INT)
    update_record_and_verify_type(driver, ion_list, IonPyList, IonType.LIST)
    update_record_and_verify_type(driver, ion_null, IonPyNull, IonType.NULL)
    update_record_and_verify_type(driver, ion_sexp, IonPyList, IonType.SEXP)
    update_record_and_verify_type(driver, ion_string, IonPyText, IonType.STRING)
    update_record_and_verify_type(driver, ion_struct, IonPyDict, IonType.STRUCT)
    update_record_and_verify_type(driver, ion_symbol, IonPySymbol, IonType.SYMBOL)
    update_record_and_verify_type(driver, ion_timestamp, IonPyTimestamp, IonType.TIMESTAMP)
    update_record_and_verify_type(driver, ion_null_clob, IonPyNull, IonType.CLOB)
    update_record_and_verify_type(driver, ion_null_blob, IonPyNull, IonType.BLOB)
    update_record_and_verify_type(driver, ion_null_bool, IonPyNull, IonType.BOOL)
    update_record_and_verify_type(driver, ion_null_decimal, IonPyNull, IonType.DECIMAL)
    update_record_and_verify_type(driver, ion_null_float, IonPyNull, IonType.FLOAT)
    update_record_and_verify_type(driver, ion_null_int, IonPyNull, IonType.INT)
    update_record_and_verify_type(driver, ion_null_list, IonPyNull, IonType.LIST)
    update_record_and_verify_type(driver, ion_null_sexp, IonPyNull, IonType.SEXP)
    update_record_and_verify_type(driver, ion_null_string, IonPyNull, IonType.STRING)
    update_record_and_verify_type(driver, ion_null_struct, IonPyNull, IonType.STRUCT)
    update_record_and_verify_type(driver, ion_null_symbol, IonPyNull, IonType.SYMBOL)
    update_record_and_verify_type(driver, ion_null_timestamp, IonPyNull, IonType.TIMESTAMP)
    delete_table(driver, TABLE_NAME)


def main(ledger_name=Constants.LEDGER_NAME):
    """
    Insert all the supported Ion types and Python values that are convertible to Ion into a ledger and verify that they
    are stored and can be retrieved properly, retaining their original properties.
    """
    try:
        with create_qldb_driver(ledger_name) as driver:
            insert_and_verify_ion_types(driver)
    except Exception as e:
        logger.exception('Error updating and validating Ion types.')
        raise e


if __name__ == '__main__':
    main()
```

------