

# 了解如何从 SQL 转向 NoSQL
<a name="SQLtoNoSQL"></a>

如果您是应用程序开发人员，则可能在使用关系数据库管理系统 (RDBMS) 和结构化查询语言 (SQL) 方面有一些经验。在您开始使用 Amazon DynamoDB 时，您既会遇到许多相似之处，也会遇到许多不同之处。*NoSQL* 是一个术语，用于描述高度可用的、可扩展的并且已针对高性能进行优化的非关系数据库系统。有别于关系模型，NoSQL 数据库（如 DynamoDB）使用替代模型进行数据管理，例如键-值对或文档存储。有关更多信息，请参阅 [NoSQL 是什么?](https://aws.amazon.com/nosql)。

Amazon DynamoDB 支持 [PartiQL](https://partiql.org/)，后者一种与 SQL 兼容的开源查询语言，使您可以轻松、高效地查询数据，无论数据存储在何处或以何种格式存储。使用 PartiQL，您可以轻松处理关系数据库中的结构化数据、采用开放数据格式的半结构化和嵌套数据，甚至可以处理允许不同行中使用不同属性的 NoSQL 或文档数据库中的无模式数据。有关更多信息，请参阅 [PartiQL 查询语言](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/ql-reference.html)。

下节介绍常见数据库任务，并将 SQL 语句与其等效 DynamoDB 操作进行比较和对比。

**注意**  
本部分中的 SQL 示例可与 MySQL RDBMS 兼容。  
本节中的 DynamoDB 示例显示 DynamoDB 操作的名称以及该操作的参数（采用 JSON 格式）。

**Topics**
+ [在关系（SQL）和 NoSQL 之间进行选择](SQLtoNoSQL.WhyDynamoDB.md)
+ [关系（SQL）数据库和 DynamoDB 在访问方式方面的差异](SQLtoNoSQL.Accessing.md)
+ [关系（SQL）数据库和 DynamoDB 在创建表方面的差异](SQLtoNoSQL.CreateTable.md)
+ [从关系（SQL）数据库与从 DynamoDB 获取表信息方面的差异](SQLtoNoSQL.GetTableInfo.md)
+ [关系（SQL）数据库和 DynamoDB 在向表写入数据方面的差异](SQLtoNoSQL.WriteData.md)
+ [关系（SQL）数据库和 DynamoDB 在从表中读取数据方面的差异](SQLtoNoSQL.ReadData.md)
+ [关系（SQL）数据库和 DynamoDB 在管理索引方面的差异](SQLtoNoSQL.Indexes.md)
+ [关系（SQL）数据库和 DynamoDB 在修改表中的数据方面的差异](SQLtoNoSQL.UpdateData.md)
+ [关系（SQL）数据库和 DynamoDB 在从表中删除数据方面的差异](SQLtoNoSQL.DeleteData.md)
+ [关系（SQL）数据库和 DynamoDB 在删除表方面的差异](SQLtoNoSQL.RemoveTable.md)

# 在关系（SQL）和 NoSQL 之间进行选择
<a name="SQLtoNoSQL.WhyDynamoDB"></a>

如今，应用程序的要求比以往更严苛。例如，在线游戏一开始时只有几个用户和极少数据。但是，如果游戏获得成功，则可以轻松超过基础数据库管理系统的资源。基于 Web 的应用程序拥有数百、数千或数百万并发用户，并且每天生成数 TB 或更多新数据，这并不少见。此类应用程序的数据库必须每秒处理数万或数十万次读取和写入。

Amazon DynamoDB 非常适合这些类型的工作负载。作为开发人员，您首先可以使用较低的使用率，然后随着应用程序变得越来越受欢迎而逐渐增加使用率。DynamoDB 无缝扩展以处理大量数据和大量用户。

有关传统关系数据库建模以及如何使其适用于 DynamoDB 的更多信息，请参阅[在 DynamoDB 中建模关系数据的最佳实践](bp-relational-modeling.md)。

下表显示了关系数据库管理系统（RDBMS）和 DynamoDB 之间的一些高级差异。


****  

| 特征 | 关系数据库管理系统（RDBMS） | Amazon DynamoDB | 
| --- | --- | --- | 
| 最佳工作负载 | 临时查询；数据仓库；OLAP (联机分析处理)。 | Web 规模级应用程序，包括社交网络、游戏、媒体共享和物联网 (IoT)。 | 
| 数据模型 | 关系模型需要一个明确定义的架构，其中，数据将标准化为表、列和行。此外，在表、列、索引和其他数据库元素之间定义所有关系。 | DynamoDB 无架构。每个表必须具有一个用来唯一标识每个数据项目的主键，但对其他非键属性没有类似的约束。DynamoDB 可以管理结构化或半结构化数据，包括 JSON 文档。 | 
| 数据访问 | SQL 是存储和检索数据的标准。关系数据库提供一组丰富的工具来简化数据库驱动型应用程序的开发，但所有这些工具都使用 SQL。 | 您可以使用 AWS 管理控制台、AWS CLI 或 NoSQL WorkBench 来操作 DynamoDB 并执行临时任务。[PartiQL](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/ql-reference.html) 是一种与 SQL 兼容的查询语言，它使您能够在 DynamoDB 中选择、插入、更新和输出数据。应用程序可以使用 AWS 开发工具包 (SDK)，通过基于对象的、以文档为中心的或低级别的接口来操作 DynamoDB。 | 
| 性能： | 关系数据库已针对存储进行优化，因此，性能通常取决于磁盘子系统。开发人员和数据库管理员必须优化查询、索引和表结构以实现最高性能。 | DynamoDB 已针对计算进行优化，因此，性能主要取决于基础硬件和网络延迟。作为一项托管服务，DynamoDB 可使您和您的应用程序免受这些实施详细信息的影响，以便您能够专注于设计和构建可靠的、高性能的应用程序。 | 
| 扩展 | 利用更快的硬件进行向上扩展是最轻松的。此外，数据库表可以跨越分布式系统中的多个主机，只不过这需要额外的投资。关系数据库设定了文件数和文件大小的最大值，这将对可扩展性施加上限。 | DynamoDB 设计为使用硬件的分布式集群来向外扩展。此设计可提高吞吐量而不会增加延迟。客户指定其吞吐量要求，DynamoDB 会分配足够的资源来满足这些要求。对于每个表的项目数和表的总大小都不施加上限。 | 

# 关系（SQL）数据库和 DynamoDB 在访问方式方面的差异
<a name="SQLtoNoSQL.Accessing"></a>

要让您的应用程序能够访问数据库，其必须经过*身份验证*，以确保该应用程序能够使用数据库。此外，您的应用程序还必须获得*授权*，以使该应用程序只能执行它有权执行的操作。

下图说明客户端与关系数据库和 Amazon DynamoDB 之间的交互。

![\[与关系数据库和 NoSQL 数据库的交互。\]](http://docs.aws.amazon.com/zh_cn/amazondynamodb/latest/developerguide/images/SQLtoNoSQL.png)


下表包含有关客户端交互任务的更多详细信息。


****  

| 特征 | 关系数据库管理系统（RDBMS） | Amazon DynamoDB | 
| --- | --- | --- | 
| 用于访问数据库的工具 |  大多数关系数据库提供了命令行界面 (CLI)，以便您能够输入临时 SQL 语句并立即查看结果。  | 大多数情况下，您将编写应用程序代码。此外，您还可以使用 AWS 管理控制台、AWS Command Line Interface (AWS CLI) 或 NoSQL 向 DynamoDB 发送临时请求并查看结果。[PartiQL](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/ql-reference.html) 是一种与 SQL 兼容的查询语言，它使您能够在 DynamoDB 中选择、插入、更新和输出数据。 | 
| 连接到数据库 | 应用程序会建立和维护与数据库的网络连接。当应用程序完成时，它将终止连接。 | DynamoDB 是一项 Web 服务，与其进行的交互是无状态的。应用程序不需要维护持久性网络连接。相反，与 DynamoDB 的交互是通过 HTTP(S) 请求和响应进行的。 | 
| 身份验证 | 应用程序在经过身份验证之前无法连接到数据库。RDBMS 可自行执行身份验证，也可以将该任务分载到主机操作系统或目录服务。 | 对 DynamoDB 发出的每个请求均必须附有一个加密签名，此签名将对特殊请求进行身份验证。AWS SDK 提供了创建签名和签署请求所需的所有逻辑。有关更多信息，请参阅《AWS 一般参考》中的[签署 AWS API 请求](https://docs.aws.amazon.com/general/latest/gr/signing_aws_api_requests.html)。 | 
| Authorization\$1 | 应用程序只能执行自身获得授权的操作。数据库管理员或应用程序所有者可以使用 SQL GRANT 和 REVOKE 语句来控制对数据库对象 (如表) 、数据 (如表中的行) 或发出某些 SQL 语句的功能的访问权。 | 在 DynamoDB 中，由 AWS Identity and Access Management (IAM) 处理授权。您可以编写 IAM policy 来授予针对 DynamoDB 资源（如表）的权限，然后允许用户和角色使用该策略。IAM 还具有针对 DynamoDB 表中各个数据项的精细访问控制功能。有关更多信息，请参阅 [适用于 Amazon DynamoDB 的 Identity and Access Management](security-iam.md)。 | 
| 发送请求 | 应用程序为要执行的每个数据库操作发出一个 SQL 语句。收到 SQL 语句后，RDBMS 将检查其语法，创建执行操作的计划，然后执行该计划。 | 应用程序将 HTTP(S) 请求发送到 DynamoDB。该请求包含要执行的 DynamoDB 操作的名称和参数。DynamoDB 立即运行请求。 | 
| 接收响应 | RDBMS 返回来自 SQL 语句的结构。如果出错，RDBMS 将返回错误状态和消息。 | DynamoDB 返回一个包含操作结果的 HTTP(S) 响应。如果出错，DynamoDB 将返回 HTTP 错误状态和消息。 | 

# 关系（SQL）数据库和 DynamoDB 在创建表方面的差异
<a name="SQLtoNoSQL.CreateTable"></a>

表是关系数据库和 Amazon DynamoDB 中的基本数据结构。关系数据库管理系统 (RDBMS) 要求您在创建表时定义表的架构。相比之下，DynamoDB 表没有架构—与主键不同，您在创建表时无需定义任何属性或数据类型。

以下章节将使用 SQL 创建表的方式与使用 DynamoDB 创建表的方式进行了比较。

**Topics**
+ [使用 SQL 创建表](#SQLtoNoSQL.CreateTable.SQL)
+ [使用 DynamoDB 创建表](#SQLtoNoSQL.CreateTable.DynamoDB)

## 使用 SQL 创建表
<a name="SQLtoNoSQL.CreateTable.SQL"></a>

通过 SQL，您将使用 `CREATE TABLE` 语句创建表，如以下示例所示。

```
CREATE TABLE Music (
    Artist VARCHAR(20) NOT NULL,
    SongTitle VARCHAR(30) NOT NULL,
    AlbumTitle VARCHAR(25),
    Year INT,
    Price FLOAT,
    Genre VARCHAR(10),
    Tags TEXT,
    PRIMARY KEY(Artist, SongTitle)
);
```

此表的主键包含 *Artist* 和 *SongTitle*。

您必须定义表的所有列和数据类型以及表的主键。(如有必要，您稍后可以使用 `ALTER TABLE` 语句更改这些定义。)

许多 SQL 实现可让您将表的存储规范定义为 `CREATE TABLE` 语句的一部分。除非另外指明，否则使用默认存储设置创建表。在生产环境中，数据库管理员可以帮助确定最佳存储参数。

## 使用 DynamoDB 创建表
<a name="SQLtoNoSQL.CreateTable.DynamoDB"></a>

使用 `CreateTable` 操作可创建预调配的模式表，同时指定参数，如下所示：

```
{
    TableName : "Music",
    KeySchema: [
        {
            AttributeName: "Artist",
            KeyType: "HASH" //Partition key
        },
        {
            AttributeName: "SongTitle",
            KeyType: "RANGE" //Sort key
        }
    ],
    AttributeDefinitions: [
        {
            AttributeName: "Artist",
            AttributeType: "S"
        },
        {
            AttributeName: "SongTitle",
            AttributeType: "S"
        }
    ],
    ProvisionedThroughput: {       // Only specified if using provisioned mode
        ReadCapacityUnits: 1,
        WriteCapacityUnits: 1
    }
}
```

此表的主键包括 *Artist*（分区键）和 *SongTitle*（排序键）。

您必须向 `CreateTable` 提供以下参数：
+ `TableName` – 表名称。
+ `KeySchema` – 用于主键的属性。有关更多信息，请参阅[表、项目和属性](HowItWorks.CoreComponents.md#HowItWorks.CoreComponents.TablesItemsAttributes)和[主键](HowItWorks.CoreComponents.md#HowItWorks.CoreComponents.PrimaryKey)。
+ `AttributeDefinitions` – 键架构属性的数据类型。
+ `ProvisionedThroughput (for provisioned tables)` – 每秒需对此表执行的读取和写入次数。DynamoDB 将保留足量的存储和系统资源，以便始终满足您的吞吐量需求。如有必要，您稍后可使用 `UpdateTable` 操作后更改这些设置。由于存储分配完全由 DynamoDB 管理，因此您无需指定表的存储要求。

# 从关系（SQL）数据库与从 DynamoDB 获取表信息方面的差异
<a name="SQLtoNoSQL.GetTableInfo"></a>

您可以根据您的规范验证是否已创建表。关系数据库中显示了所有表的架构。Amazon DynamoDB 表没有架构，因此仅显示主键属性。

**Topics**
+ [使用 SQL 获取有关表的信息](#SQLtoNoSQL.GetTableInfo.SQL)
+ [在 DynamoDB 中获取有关表的信息](#SQLtoNoSQL.GetTableInfo.DynamoDB)

## 使用 SQL 获取有关表的信息
<a name="SQLtoNoSQL.GetTableInfo.SQL"></a>

大多数关系数据库管理系统 (RDBMS) 允许您描述表的结构—列、数据类型、主键定义等。在 SQL 中，没有执行此任务的标准方法。不过，许多数据库系统提供了 `DESCRIBE` 命令。以下是 MySQL 的一个示例。

```
DESCRIBE Music;
```

这将返回表的结构以及所有列名称、数据类型和大小。

```
+------------+-------------+------+-----+---------+-------+
| Field      | Type        | Null | Key | Default | Extra |
+------------+-------------+------+-----+---------+-------+
| Artist     | varchar(20) | NO   | PRI | NULL    |       |
| SongTitle  | varchar(30) | NO   | PRI | NULL    |       |
| AlbumTitle | varchar(25) | YES  |     | NULL    |       |
| Year       | int(11)     | YES  |     | NULL    |       |
| Price      | float       | YES  |     | NULL    |       |
| Genre      | varchar(10) | YES  |     | NULL    |       |
| Tags       | text        | YES  |     | NULL    |       |
+------------+-------------+------+-----+---------+-------+
```

此表的主键包含 *Artist* 和 *SongTitle*。

## 在 DynamoDB 中获取有关表的信息
<a name="SQLtoNoSQL.GetTableInfo.DynamoDB"></a>

DynamoDB 具有与之类似的 `DescribeTable` 操作。唯一的参数是表名称。

```
{
    TableName : "Music"
}
```

来自 `DescribeTable` 的回复如下所示。

```
{
  "Table": {
    "AttributeDefinitions": [
      {
        "AttributeName": "Artist",
        "AttributeType": "S"
      },
      {
        "AttributeName": "SongTitle",
        "AttributeType": "S"
      }
    ],
    "TableName": "Music",
    "KeySchema": [
      {
        "AttributeName": "Artist",
        "KeyType": "HASH"  //Partition key
      },
      {
        "AttributeName": "SongTitle",
        "KeyType": "RANGE"  //Sort key
      }
    ],

    ...
```

`DescribeTable` 还返回有关表中的索引、预置的吞吐量设置、大约项目数和其他元数据的信息。

# 关系（SQL）数据库和 DynamoDB 在向表写入数据方面的差异
<a name="SQLtoNoSQL.WriteData"></a>

关系数据库表包含数据*行*。行由*列*组成。Amazon DynamoDB 表包含*项目*。项目由*属性* 组成。

本节介绍如何将一行（或一个项目）写入表。

**Topics**
+ [使用 SQL 将数据写入表](#SQLtoNoSQL.WriteData.SQL)
+ [在 DynamoDB 中将数据写入表](#SQLtoNoSQL.WriteData.DynamoDB)

## 使用 SQL 将数据写入表
<a name="SQLtoNoSQL.WriteData.SQL"></a>

关系数据库中的表是一个由行和列组成的二维数据结构。一些数据库管理系统还支持半结构化数据（通常包括原生 JSON 或 XML 数据类型）。但实施详情因供应商而异。

在 SQL 中，您将使用 `INSERT` 语句向表添加行。

```
INSERT INTO Music
    (Artist, SongTitle, AlbumTitle,
    Year, Price, Genre,
    Tags)
VALUES(
    'No One You Know', 'Call Me Today', 'Somewhat Famous',
    2015, 2.14, 'Country',
    '{"Composers": ["Smith", "Jones", "Davis"],"LengthInSeconds": 214}'
);
```

此表的主键包含 *Artist* 和 *SongTitle*。您必须为这些列指定值。

**注意**  
该示例使用 *Tags* 列存储有关 *Music* 表中歌曲的半结构化数据。*Tags* 列定义为类型 TEXT，可在 MySQL 中存储最多 65535 个字符。

## 在 DynamoDB 中将数据写入表
<a name="SQLtoNoSQL.WriteData.DynamoDB"></a>

在 Amazon DynamoDB 中，您可以使用 DynamoDB API 或 [PartiQL](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/ql-reference.html)（一种与 SQL 兼容的查询语言）将项目添加到表中。

------
#### [ DynamoDB API ]

使用 DynamoDB API，您可以使用 `PutItem` 操作向表添加项目。

```
{
    TableName: "Music",
    Item: {
        "Artist":"No One You Know",
        "SongTitle":"Call Me Today",
        "AlbumTitle":"Somewhat Famous",
        "Year": 2015,
        "Price": 2.14,
        "Genre": "Country",
        "Tags": {
            "Composers": [
                  "Smith",
                  "Jones",
                  "Davis"
            ],
            "LengthInSeconds": 214
        }
    }
}
```

此表的主键包含 *Artist* 和 *SongTitle*。您必须为这些属性指定值。

以下是要了解的有关此 `PutItem` 示例的几个关键事项：
+ DynamoDB 使用 JSON 提供对文档的原生支持。这使得 DynamoDB 非常适合存储半结构化数据，例如*标记*。您也可以从 JSON 文档中检索和操作数据。
+ 除了主键（*Artist* 和 *SongTitle*）外，*Music* 表没有任何预定义属性。
+ 大多数 SQL 数据库是面向事务的。当您发出 `INSERT` 语句时，数据修改不是永久性的，直至您发出 `COMMIT` 语句。利用 Amazon DynamoDB，当 DynamoDB 回复 HTTP 200 状态代码（`OK`）时，`PutItem` 操作的效果是永久性的。

以下是其他几个 `PutItem` 示例。

```
{
    TableName: "Music",
    Item: {
        "Artist": "No One You Know",
        "SongTitle": "My Dog Spot",
        "AlbumTitle":"Hey Now",
        "Price": 1.98,
        "Genre": "Country",
        "CriticRating": 8.4
    }
}
```

```
{
    TableName: "Music",
    Item: {
        "Artist": "No One You Know",
        "SongTitle": "Somewhere Down The Road",
        "AlbumTitle":"Somewhat Famous",
        "Genre": "Country",
        "CriticRating": 8.4,
        "Year": 1984
    }
}
```

```
{
    TableName: "Music",
    Item: {
        "Artist": "The Acme Band",
        "SongTitle": "Still In Love",
        "AlbumTitle":"The Buck Starts Here",
        "Price": 2.47,
        "Genre": "Rock",
        "PromotionInfo": {
            "RadioStationsPlaying":[
                 "KHCR", "KBQX", "WTNR", "WJJH"
            ],
            "TourDates": {
                "Seattle": "20150625",
                "Cleveland": "20150630"
            },
            "Rotation": "Heavy"
        }
    }
}
```

```
{
    TableName: "Music",
    Item: {
        "Artist": "The Acme Band",
        "SongTitle": "Look Out, World",
        "AlbumTitle":"The Buck Starts Here",
        "Price": 0.99,
        "Genre": "Rock"
    }
}
```

**注意**  
除了 `PutItem` 之外，DynamoDB 还支持使用 `BatchWriteItem` 操作同时写入多个项目。

------
#### [ PartiQL for DynamoDB ]

使用 PartiQL，您可以通过使用 PartiQL `Insert` 语句来使用 `ExecuteStatement` 操作向表添加项目。

```
INSERT into Music value {  
    'Artist': 'No One You Know',
    'SongTitle': 'Call Me Today',
    'AlbumTitle': 'Somewhat Famous',
    'Year' : '2015',
    'Genre' : 'Acme'
}
```

此表的主键包含 *Artist* 和 *SongTitle*。您必须为这些属性指定值。

**注意**  
有关使用 `Insert` 和 `ExecuteStatement` 的代码示例，请参阅 [PartiQL for DynamoDB Insert 语句](ql-reference.insert.md)。

------

# 关系（SQL）数据库和 DynamoDB 在从表中读取数据方面的差异
<a name="SQLtoNoSQL.ReadData"></a>

利用 SQL，您可使用 `SELECT` 语句从表中检索一个或多个行。可使用 `WHERE` 子句来确定返回给您的数据。

这与使用 Amazon DynamoDB 不同，后者提供以下操作来读取数据：
+ `ExecuteStatement` 将会检索表中的单个或多个项目。`BatchExecuteStatement` 可以通过单个操作检索不同表中的多个项目。所有这些操作均使用 [PartiQL](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/ql-reference.html)，一种 SQL 兼容的查询语言。
+ `GetItem` – 从表中检索单个项目。这是读取单个项目的最高效方式，因为它将提供对项目物理位置的直接访问。（DynamoDB 还提供 `BatchGetItem` 操作，允许在单个操作中执行最多 100 次 `GetItem` 调用。）
+ `Query` – 检索具有特定分区键的所有项目。在这些项目中，您可以将条件应用于排序键并仅检索一部分数据。`Query` 针对存储数据的分区提供快速、高效的访问。（有关更多信息，请参阅 [DynamoDB 中的分区和数据分布](HowItWorks.Partitions.md)。）
+ `Scan` – 检索指定表中的所有项目。（不应对大型表使用此操作，因为这可能会占用大量系统资源。）

**注意**  
利用关系数据库，您可以使用 `SELECT` 语句联接多个表中的数据并返回结果。联接是关系模型的基础。要确保联接高效运行，应持续优化数据库及其应用程序的性能。DynamoDB 是一个不支持表连接的非关系 NoSQL 数据库。相反，应用程序一次从一个表中读取数据。

以下各节介绍读取数据的各种使用案例，以及如何使用关系数据库和 DynamoDB 执行这些任务。

**Topics**
+ [使用项目的主键读取项目方面的差异](SQLtoNoSQL.ReadData.SingleItem.md)
+ [查询表方面的差异](SQLtoNoSQL.ReadData.Query.md)
+ [扫描表方面的差异](SQLtoNoSQL.ReadData.Scan.md)

# 使用项目的主键读取项目方面的差异
<a name="SQLtoNoSQL.ReadData.SingleItem"></a>

数据库的一个常见访问模式是从表中读取一个项目。您必须指定所需项目的主键。

**Topics**
+ [通过 SQL 使用项目的主键读取项目](#SQLtoNoSQL.ReadData.SingleItem.SQL)
+ [在 DynamoDB 中使用项目的主键读取项目](#SQLtoNoSQL.ReadData.SingleItem.DynamoDB)

## 通过 SQL 使用项目的主键读取项目
<a name="SQLtoNoSQL.ReadData.SingleItem.SQL"></a>

在 SQL 中，您将使用 `SELECT` 语句从表中检索数据。您可以在结果中请求一个或多个列 (或所有列，如果您使用 `*` 运算符)。`WHERE` 子句确定要返回的行。

以下是 `SELECT` 语句，它从 *Music* 表中检索单个行。`WHERE` 子句指定主键值。

```
SELECT *
FROM Music
WHERE Artist='No One You Know' AND SongTitle = 'Call Me Today'
```

您可以修改此查询以仅检索一部分列。

```
SELECT AlbumTitle, Year, Price
FROM Music
WHERE Artist='No One You Know' AND SongTitle = 'Call Me Today'
```

请注意，此表的主键包含 *Artist* 和 *SongTitle*。

## 在 DynamoDB 中使用项目的主键读取项目
<a name="SQLtoNoSQL.ReadData.SingleItem.DynamoDB"></a>

在 Amazon DynamoDB 中，您可以使用 DynamoDB API 或 [PartiQL](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/ql-reference.html)（一种与 SQL 兼容的查询语言）读取表中的项目。

------
#### [ DynamoDB API ]

使用 DynamoDB API，您可以使用 `PutItem` 操作向表添加项目。

DynamoDB 提供 `GetItem` 操作来按项目的主键检索项目。`GetItem` 非常高效，因为它提供对项目物理位置的直接访问。（有关更多信息，请参阅 [DynamoDB 中的分区和数据分布](HowItWorks.Partitions.md)。）

默认情况下，`GetItem` 将返回整个项目及其所有属性。

```
{
    TableName: "Music",
    Key: {
        "Artist": "No One You Know",
        "SongTitle": "Call Me Today"
    }
}
```

您可以添加 `ProjectionExpression` 参数以仅返回一些属性。

```
{
    TableName: "Music",
    Key: {
        "Artist": "No One You Know",
        "SongTitle": "Call Me Today"
    },
    "ProjectionExpression": "AlbumTitle, Year, Price"
}
```

请注意，此表的主键包含 *Artist* 和 *SongTitle*。

DynamoDB `GetItem` 操作非常高效。此操作使用主键值确定相关项目的确切存储位置，并直接从此位置检索该项目。在按主键值检索项目时，SQL `SELECT` 语句同样高效。

SQL `SELECT` 语句支持多种类型的查询和表扫描。DynamoDB 的 `Query` 和 `Scan` 操作功能类似，这两个操作在 [查询表方面的差异](SQLtoNoSQL.ReadData.Query.md) 和 [扫描表方面的差异](SQLtoNoSQL.ReadData.Scan.md) 中介绍。

SQL `SELECT` 语句可执行表联接，这允许您同时从多个表中检索数据。在标准化数据库表的情况下，联接是最高效的，并且各个表之间的关系很明确。不过，如果您在一个 `SELECT` 语句中联接的表过多，则会影响应用程序性能。可使用数据库复制、具体化的视图或查询重写来解决此类问题。

DynamoDB 是一个非关系数据库且不支持表联接。如果您将现有应用程序从关系数据库迁移到 DynamoDB，则需要非规范化数据模型以消除联接需要。

------
#### [ PartiQL for DynamoDB ]

使用 PartiQL，您可以通过使用 PartiQL `ExecuteStatement` 语句来使用 `Select` 操作读取表中的项目。

```
SELECT AlbumTitle, Year, Price
FROM Music
WHERE Artist='No One You Know' AND SongTitle = 'Call Me Today'
```

请注意，此表的主键包含 Artist 和 SongTitle。

**注意**  
 选择 PartiSQL 语句也可用于查询或扫描 DynamoDB 表

有关使用 `Select` 和 `ExecuteStatement` 的代码示例，请参阅 [PartiQL for DynamoDB 的 Select 语句](ql-reference.select.md)。

------

# 查询表方面的差异
<a name="SQLtoNoSQL.ReadData.Query"></a>

另一个常见访问模式是根据您的查询条件从表中读取多个项目。

**Topics**
+ [使用 SQL 查询表](#SQLtoNoSQL.ReadData.Query.SQL)
+ [在 DynamoDB 中查询表](#SQLtoNoSQL.ReadData.Query.DynamoDB)

## 使用 SQL 查询表
<a name="SQLtoNoSQL.ReadData.Query.SQL"></a>

使用 SQL 时，`SELECT` 语句可让您查询关键列、非关键列或任意组合。`WHERE` 子句确定返回的行，如以下示例所示。

```
/* Return a single song, by primary key */

SELECT * FROM Music
WHERE Artist='No One You Know' AND SongTitle = 'Call Me Today';
```

```
/* Return all of the songs by an artist */

SELECT * FROM Music
WHERE Artist='No One You Know';
```

```
/* Return all of the songs by an artist, matching first part of title */

SELECT * FROM Music
WHERE Artist='No One You Know' AND SongTitle LIKE 'Call%';
```

```
/* Return all of the songs by an artist, only if the price is less than 1.00 */

SELECT * FROM Music
WHERE Artist='No One You Know'
AND Price < 1.00;
```

请注意，此表的主键包含 *Artist* 和 *SongTitle*。

## 在 DynamoDB 中查询表
<a name="SQLtoNoSQL.ReadData.Query.DynamoDB"></a>

在 Amazon DynamoDB 中，您可以使用 DynamoDB API 或 [PartiQL](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/ql-reference.html)（一种与 SQL 兼容的查询语言）查询表中的项目。

------
#### [ DynamoDB API ]

通过 Amazon DynamoDB，您可以使用 `Query` 操作以类似方式检索数据。`Query` 操作提供对存储数据的物理位置的快速高效访问。有关更多信息，请参阅 [DynamoDB 中的分区和数据分布](HowItWorks.Partitions.md)。

您可以将 `Query` 与任何表或二级索引一起使用。您必须为分区键的值指定相等条件，并且可以有选择性地为排序键属性（如果已定义）提供另一个条件。

`KeyConditionExpression` 参数指定要查询的键值。可使用可选 `FilterExpression` 在结果中的某些项目返回给您之前删除这些项目。

在 DynamoDB 中，您必须使用 `ExpressionAttributeValues` 作为表达式参数（如 `KeyConditionExpression` 和 `FilterExpression`）中的占位符。这类似于在关系数据库中使用*绑定变量*，其中，您在运行时将实际值代入 `SELECT` 语句。

请注意，此表的主键包含 *Artist* 和 *SongTitle*。

以下是其他几个 DynamoDB `Query` 示例。

```
// Return a single song, by primary key

{
    TableName: "Music",
    KeyConditionExpression: "Artist = :a and SongTitle = :t",
    ExpressionAttributeValues: {
        ":a": "No One You Know",
        ":t": "Call Me Today"
    }
}
```

```
// Return all of the songs by an artist

{
    TableName: "Music",
    KeyConditionExpression: "Artist = :a",
    ExpressionAttributeValues: {
        ":a": "No One You Know"
    }
}
```

```
// Return all of the songs by an artist, matching first part of title

{
    TableName: "Music",
    KeyConditionExpression: "Artist = :a and begins_with(SongTitle, :t)",
    ExpressionAttributeValues: {
        ":a": "No One You Know",
        ":t": "Call"
    }
}
```

```
// Return all of the songs by an artist, only if the price is less than 1.00

{
    TableName: "Music",
    KeyConditionExpression: "Artist = :a",
    FilterExpression: "Price < :p",
    ExpressionAttributeValues: {
        ":a": "No One You Know",
        ":p": 1.00
    }
}
```

**注意**  
`FilterExpression` 在 `Query` 读取匹配的项目之后应用，因此不会减少消耗的读取容量。尽可能对数据进行建模，以便范围条件可以在排序键上使用 `KeyConditionExpression` 高效地进行查询。有关更多信息，请参阅 [在 DynamoDB 中查询表](Query.md)。

------
#### [ PartiQL for DynamoDB ]

通过 PartiQL，您可以对分区键使用 `ExecuteStatement` 操作和 `Select` 语句执行查询。

```
SELECT AlbumTitle, Year, Price
FROM Music
WHERE Artist='No One You Know'
```

通过此方式使用 `SELECT` 语句将返回与此特定 `Artist` 关联的所有歌曲。

有关使用 `Select` 和 `ExecuteStatement` 的代码示例，请参阅 [PartiQL for DynamoDB 的 Select 语句](ql-reference.select.md)。

------

# 扫描表方面的差异
<a name="SQLtoNoSQL.ReadData.Scan"></a>

在 SQL 中，不带 `SELECT` 子句的 `WHERE` 语句将返回表中的每个行。在 Amazon DynamoDB 中，`Scan` 操作可执行相同的工作。在这两种情况下，您都可以检索所有项目或部分项目。

无论您使用的是 SQL 还是 NoSQL 数据库，都应谨慎使用扫描操作，因为它们会占用大量系统资源。有时，扫描是适合的 (例如，扫描小型表) 或不可避免的 (例如，执行数据的批量导出操作)。但通常来说，您应设计应用程序以避免执行扫描。有关更多信息，请参阅 [在 DynamoDB 中查询表](Query.md)。

**注意**  
执行批量导出还将为每个分区创建至少 1 个文件。每个文件中的所有项目都来自于该特定分区的哈希密钥空间。

**Topics**
+ [使用 SQL 扫描表](#SQLtoNoSQL.ReadData.Scan.SQL)
+ [在 DynamoDB 中扫描表](#SQLtoNoSQL.ReadData.Scan.DynamoDB)

## 使用 SQL 扫描表
<a name="SQLtoNoSQL.ReadData.Scan.SQL"></a>

使用 SQL 时，您可以在不指定 `SELECT` 子句的情况下使用 `WHERE` 语句扫描表并检索其所有数据。您可以在结果中请求一个或多个列。或者，如果您使用通配符 (\$1)，则可请求所有列。

以下是使用 `SELECT` 语句的示例。

```
/* Return all of the data in the table */
SELECT * FROM Music;
```

```
/* Return all of the values for Artist and Title */
SELECT Artist, Title FROM Music;
```

## 在 DynamoDB 中扫描表
<a name="SQLtoNoSQL.ReadData.Scan.DynamoDB"></a>

在 Amazon DynamoDB 中，您可以使用 DynamoDB API 或 [PartiQL](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/ql-reference.html)（一种与 SQL 兼容的查询语言）对表执行扫描。

------
#### [ DynamoDB API ]

借助 DynamoDB API，您可以使用 `Scan` 操作来通过访问表或者二级索引中的每个项目来返回一个或多个项目和项目属性。

```
// Return all of the data in the table
{
    TableName:  "Music"
}
```

```
// Return all of the values for Artist and Title
{
    TableName:  "Music",
    ProjectionExpression: "Artist, Title"
}
```

`Scan` 操作还提供一个 `FilterExpression` 参数，您可以使用它丢弃不希望在结果中出现的项目。在执行扫描后且结果返回给您之前，应用 `FilterExpression`。（不建议对大表使用。即使仅返回几个匹配项目，您仍需为整个 `Scan` 付费。）

------
#### [ PartiQL for DynamoDB ]

使用 PartiQL，您可以通过 `Select` 语句来使用 `ExecuteStatement` 操作执行扫描，以返回表的所有内容。

```
SELECT AlbumTitle, Year, Price
FROM Music
```

请注意，此语句将返回 Music 表中的所有项目。

有关使用 `Select` 和 `ExecuteStatement` 的代码示例，请参阅 [PartiQL for DynamoDB 的 Select 语句](ql-reference.select.md)。

------

# 关系（SQL）数据库和 DynamoDB 在管理索引方面的差异
<a name="SQLtoNoSQL.Indexes"></a>

索引使您能够访问替代查询模式，并可以加快查询速度。本节将 SQL 和 Amazon DynamoDB 中的索引创建和使用进行了比较和对比。

无论您使用的是关系数据库还是 DynamoDB，在创建索引时都应谨慎。只要对表进行写入，就必须更新表的所有索引。在具有大型表的写入密集型环境中，这会占用大量系统资源。在只读环境或主读环境中，这算不上一个问题。但是，您应确保索引实际上由应用程序使用，而不只是占用空间。

**Topics**
+ [关系（SQL）数据库和 DynamoDB 在创建索引方面的差异](#SQLtoNoSQL.Indexes.Creating)
+ [关系（SQL）数据库和 DynamoDB 在查询和扫描索引方面的差异](#SQLtoNoSQL.Indexes.QueryAndScan)

## 关系（SQL）数据库和 DynamoDB 在创建索引方面的差异
<a name="SQLtoNoSQL.Indexes.Creating"></a>

将 SQL 中的 `CREATE INDEX` 语句与 Amazon DynamoDB 中的 `UpdateTable` 操作进行比较。

**Topics**
+ [使用 SQL 创建索引](#SQLtoNoSQL.Indexes.Creating.SQL)
+ [在 DynamoDB 中创建索引](#SQLtoNoSQL.Indexes.Creating.DynamoDB)

### 使用 SQL 创建索引
<a name="SQLtoNoSQL.Indexes.Creating.SQL"></a>

在关系数据库中，索引是一个数据结构，可让您对表中的不同的列执行快速查询。您可以使用 `CREATE INDEX` SQL 语句将索引添加到现有表，并指定要建立索引的列。在创建索引后，您可以照常查询表中的数据，但现在数据库可使用索引快速查找表中的指定行，而不是扫描整个表。

在创建一个索引后，数据库将为您维护此索引。只要您修改表中的数据，就会自动更改索引以反映表中的更改。

在 MySQL 中，您可以创建如下所示的索引。

```
CREATE INDEX GenreAndPriceIndex
ON Music (genre, price);
```

### 在 DynamoDB 中创建索引
<a name="SQLtoNoSQL.Indexes.Creating.DynamoDB"></a>

在 DynamoDB 中，您可以创建和使用*二级索引*来实现类似目的。

DynamoDB 中的索引与其关系对应项不同。当您创建二级索引时，必须指定其键属性—分区键和排序键。创建二级索引后，可以 `Query` 或 `Scan`，就像对表一样。DynamoDB 没有查询优化程序，因此仅在 `Query` 或 `Scan` 时使用二级索引。

DynamoDB 支持两种不同的索引：
+ 全局二级索引 – 索引的主键可以是其表中的任意两个属性。
+ 本地二级索引 – 索引的分区键必须与其表的分区键相同。不过，排序键可以是任何其他属性。

DynamoDB 确保二级索引中的数据最终与其表保持一致。您可以请求对表或本地二级索引执行强一致性 `Query` 或 `Scan` 操作。但是，全局二级索引仅支持最终一致性。

可以使用 `UpdateTable` 操作并指定 `GlobalSecondaryIndexUpdates`，将全局二级索引添加到现有表。

```
{
    TableName: "Music",
    AttributeDefinitions:[
        {AttributeName: "Genre", AttributeType: "S"},
        {AttributeName: "Price", AttributeType: "N"}
    ],
    GlobalSecondaryIndexUpdates: [
        {
            Create: {
                IndexName: "GenreAndPriceIndex",
                KeySchema: [
                    {AttributeName: "Genre", KeyType: "HASH"}, //Partition key
                    {AttributeName: "Price", KeyType: "RANGE"}, //Sort key
                ],
                Projection: {
                    "ProjectionType": "ALL"
                },
                ProvisionedThroughput: {                                // Only specified if using provisioned mode
                    "ReadCapacityUnits": 1,"WriteCapacityUnits": 1
                }
            }
        }
    ]
}
```

您必须向 `UpdateTable` 提供以下参数：
+ `TableName` – 索引将关联到的表。
+ `AttributeDefinitions` – 索引的键架构属性的数据类型。
+ `GlobalSecondaryIndexUpdates` – 有关要创建的索引的详细信息：
  + `IndexName` – 索引的名称。
  + `KeySchema` – 用于索引主键的属性。
  + `Projection` – 表中要复制到索引的属性。在此情况下，`ALL` 意味着复制所有属性。
  + `ProvisionedThroughput (for provisioned tables)` – 每秒需对此索引执行的读取和写入次数。(它与表的预调配吞吐量设置是分开的。) 

在此操作中，会将表中的数据回填到新索引。在回填期间，表保持可用。但索引未准备就绪，直至其 `Backfilling` 属性从 true 变为 false。您可以使用 `DescribeTable` 操作查看此属性。

## 关系（SQL）数据库和 DynamoDB 在查询和扫描索引方面的差异
<a name="SQLtoNoSQL.Indexes.QueryAndScan"></a>

将使用 SQL 中的 SELECT 语句查询并扫描索引与使用 Amazon DynamoDB 中的 `Query` 和 `Scan` 操作查询并扫描索引进行比较。

**Topics**
+ [使用 SQL 查询并扫描索引](#SQLtoNoSQL.Indexes.QueryAndScan.SQL)
+ [在 DynamoDB 中查询并扫描索引](#SQLtoNoSQL.Indexes.QueryAndScan.DynamoDB)

### 使用 SQL 查询并扫描索引
<a name="SQLtoNoSQL.Indexes.QueryAndScan.SQL"></a>

在关系数据库中，不能直接使用索引。相反，您通过发出 `SELECT` 语句来查询表，查询优化程序可使用任何索引。

*查询优化程序* 是一个关系数据库管理系统 (RDBMS) 组件，它将评估可用索引并确定是否可使用这些索引来加快查询速度。如果索引可用来加快查询速度，则 RDBMS 会先访问索引，然后使用索引查找表中的数据。

以下几个 SQL 语句可使用 *GenreAndPriceIndex* 提高性能。我们假定 *Music* 表包含足够多的数据以促使查询优化程序决定使用此索引，而不是扫描整个表。

```
/* All of the rock songs */

SELECT * FROM Music
WHERE Genre = 'Rock';
```

```
/* All of the cheap country songs */

SELECT Artist, SongTitle, Price FROM Music
WHERE Genre = 'Country' AND Price < 0.50;
```

### 在 DynamoDB 中查询并扫描索引
<a name="SQLtoNoSQL.Indexes.QueryAndScan.DynamoDB"></a>

在 DynamoDB 中，直接对索引执行 `Query` 和 `Scan` 操作，就如同对表执行此操作一样。您可以使用 DynamoDB API 或 [PartiQL](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/ql-reference.html)（一种与 SQL 兼容的查询语言）来查询或扫描索引。您必须指定 `TableName` 和 `IndexName`。

下面是一些 DynamoDB 中对 *GenreAndPriceIndex* 的查询。（此索引的键架构包含 *Genre* 和 *Price*。）

------
#### [ DynamoDB API ]

```
// All of the rock songs

{
    TableName: "Music",
    IndexName: "GenreAndPriceIndex",
    KeyConditionExpression: "Genre = :genre",
    ExpressionAttributeValues: {
        ":genre": "Rock"
    },
};
```

此示例使用 `ProjectionExpression` 指示您只希望结果中显示部分而不是全部属性。

```
// All of the cheap country songs

{
    TableName: "Music",
    IndexName: "GenreAndPriceIndex",
    KeyConditionExpression: "Genre = :genre and Price < :price",
    ExpressionAttributeValues: {
        ":genre": "Country",
        ":price": 0.50
    },
    ProjectionExpression: "Artist, SongTitle, Price"
};
```

以下是对 *GenreAndPriceIndex* 进行的扫描。

```
// Return all of the data in the index

{
    TableName:  "Music",
    IndexName: "GenreAndPriceIndex"
}
```

------
#### [ PartiQL for DynamoDB ]

使用 PartiQL，您可以使用 `Select` 语句来对索引执行查询和扫描。

```
// All of the rock songs

SELECT * 
FROM Music.GenreAndPriceIndex
WHERE Genre = 'Rock'
```

```
// All of the cheap country songs

SELECT * 
FROM Music.GenreAndPriceIndex
WHERE Genre = 'Rock' AND Price < 0.50
```

以下是对 *GenreAndPriceIndex* 进行的扫描。

```
// Return all of the data in the index

SELECT *
FROM Music.GenreAndPriceIndex
```

**注意**  
有关使用 `Select` 的代码示例，请参阅 [PartiQL for DynamoDB 的 Select 语句](ql-reference.select.md)。

------

# 关系（SQL）数据库和 DynamoDB 在修改表中的数据方面的差异
<a name="SQLtoNoSQL.UpdateData"></a>

SQL 语言提供 `UPDATE` 语句来修改数据。Amazon DynamoDB 使用 `UpdateItem` 操作来完成类似的任务。

**Topics**
+ [使用 SQL 修改表中的数据](#SQLtoNoSQL.UpdateData.SQL)
+ [在 DynamoDB 中修改表中的数据](#SQLtoNoSQL.UpdateData.DynamoDB)

## 使用 SQL 修改表中的数据
<a name="SQLtoNoSQL.UpdateData.SQL"></a>

在 SQL 中，您将使用 `UPDATE` 语句修改一个或多个行。`SET` 子句为一个或多个列指定新值，`WHERE` 子句确定修改的行。示例如下：

```
UPDATE Music
SET RecordLabel = 'Global Records'
WHERE Artist = 'No One You Know' AND SongTitle = 'Call Me Today';
```

如果任何行均不匹配 `WHERE` 子句，则 `UPDATE` 语句不起作用。

## 在 DynamoDB 中修改表中的数据
<a name="SQLtoNoSQL.UpdateData.DynamoDB"></a>

在 DynamoDB 中，您可以使用 DynamoDB API 或 [PartiQL](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/ql-reference.html)（一种与 SQL 兼容的查询语言）修改单个项目。（如果要修改多个项目，则必须使用多个操作。）

------
#### [ DynamoDB API ]

借助 DynamoDB API，您可以使用 `UpdateItem` 操作修改单个项目。

```
{
    TableName: "Music",
    Key: {
        "Artist":"No One You Know",
        "SongTitle":"Call Me Today"
    },
    UpdateExpression: "SET RecordLabel = :label",
    ExpressionAttributeValues: {
        ":label": "Global Records"
    }
}
```

必须指定要修改的项目的 `Key` 属性和 `UpdateExpression` 才能指定属性值。`UpdateItem` 行为类似于“upsert”操作。如果表中存在该项目，则会对其进行更新，但如果不存在，则会添加（插入）一个新项目。

`UpdateItem` 支持*条件写入*，在此情况下，操作仅在特定 `ConditionExpression` 的计算结果为 true 时成功完成。例如，除非歌曲的价格大于或等于 2.00，否则以下 `UpdateItem` 操作不会执行更新。

```
{
    TableName: "Music",
    Key: {
        "Artist":"No One You Know",
        "SongTitle":"Call Me Today"
    },
    UpdateExpression: "SET RecordLabel = :label",
    ConditionExpression: "Price >= :p",
    ExpressionAttributeValues: {
        ":label": "Global Records",
        ":p": 2.00
    }
}
```

`UpdateItem` 还支持*原子计数器* 或类型为 `Number` 的属性（可递增或递减）。原子计数器在很多方面都类似于 SQL 数据库中的顺序生成器、身份列或自递增字段。

以下是一个 `UpdateItem` 操作的示例，它初始化一个新属性（*Plays*）来跟踪歌曲的已播放次数。

```
{
    TableName: "Music",
    Key: {
        "Artist":"No One You Know",
        "SongTitle":"Call Me Today"
    },
    UpdateExpression: "SET Plays = :val",
    ExpressionAttributeValues: {
        ":val": 0
    },
    ReturnValues: "UPDATED_NEW"
}
```

`ReturnValues` 参数设置为 `UPDATED_NEW`，这将返回已更新的任何属性的新值。在此示例中，它返回 0 (零)。

当某人播放此歌曲时，可使用以下 `UpdateItem` 操作来将*播放次数*增加 1。

```
{
    TableName: "Music",
    Key: {
        "Artist":"No One You Know",
        "SongTitle":"Call Me Today"
    },
    UpdateExpression: "SET Plays = Plays + :incr",
    ExpressionAttributeValues: {
        ":incr": 1
    },
    ReturnValues: "UPDATED_NEW"
}
```

------
#### [ PartiQL for DynamoDB ]

使用 PartiQL，您可以通过使用 PartiQL `ExecuteStatement` 语句来使用 `Update` 操作修改表中的项目。

此表的主键包含 *Artist* 和 *SongTitle*。您必须为这些属性指定值。

```
UPDATE Music
SET RecordLabel ='Global Records'
WHERE Artist='No One You Know' AND SongTitle='Call Me Today'
```

如下例所示，您还可以一次修改多个字段。

```
UPDATE Music
SET RecordLabel = 'Global Records'
SET AwardsWon = 10
WHERE Artist ='No One You Know' AND SongTitle='Call Me Today'
```

`Update` 还支持*原子计数器* 或类型为 `Number` 的属性（可递增或递减）。原子计数器在很多方面都类似于 SQL 数据库中的顺序生成器、身份列或自递增字段。

以下是一个 `Update` 语句的示例，它初始化一个新属性 (*Plays*) 来跟踪歌曲的已播放次数。

```
UPDATE Music
SET Plays = 0
WHERE Artist='No One You Know' AND SongTitle='Call Me Today'
```

当某人播放此歌曲时，可使用以下 `Update` 语句来将 *Plays* 增加 1。

```
UPDATE Music
SET Plays = Plays + 1
WHERE Artist='No One You Know' AND SongTitle='Call Me Today'
```

**注意**  
有关使用 `Update` 和 `ExecuteStatement` 的代码示例，请参阅 [PartiQL for DynamoDB Update 语句](ql-reference.update.md)。

------

# 关系（SQL）数据库和 DynamoDB 在从表中删除数据方面的差异
<a name="SQLtoNoSQL.DeleteData"></a>

在 SQL 中，`DELETE` 语句从表检索一个或多个行。Amazon DynamoDB 使用 `DeleteItem` 操作一次删除一个项目。

**Topics**
+ [使用 SQL 删除表中的数据](#SQLtoNoSQL.DeleteData.SQL)
+ [在 DynamoDB 中删除表中的数据](#SQLtoNoSQL.DeleteData.DynamoDB)

## 使用 SQL 删除表中的数据
<a name="SQLtoNoSQL.DeleteData.SQL"></a>

在 SQL 中，可使用 `DELETE` 语句删除一个或多个行。`WHERE` 子句确定要修改的行。示例如下：

```
DELETE FROM Music
WHERE Artist = 'The Acme Band' AND SongTitle = 'Look Out, World';
```

您可以修改 `WHERE` 子句以删除多个行。例如，您可以删除某个特定艺术家的所有歌曲，如以下示例所示。

```
DELETE FROM Music WHERE Artist = 'The Acme Band'
```

## 在 DynamoDB 中删除表中的数据
<a name="SQLtoNoSQL.DeleteData.DynamoDB"></a>

在 DynamoDB 中，您可以使用 DynamoDB API 或 [PartiQL](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/ql-reference.html)（一种与 SQL 兼容的查询语言）删除单个项目。（如果要修改多个项目，则必须使用多个操作。）

------
#### [ DynamoDB API ]

借助 DynamoDB API，您可以使用 `DeleteItem` 操作删除表中的数据（一次删除一个项目）。您必须指定项目的主键值。

```
{
    TableName: "Music",
    Key: {
        Artist: "The Acme Band",
        SongTitle: "Look Out, World"
    }
}
```

**注意**  
除了 `DeleteItem` 之外，Amazon DynamoDB 还支持使用 `BatchWriteItem` 操作同时删除多个项目。

`DeleteItem` 支持*条件写入*，在此情况下，操作仅在特定 `ConditionExpression` 的计算结果为 true 时成功完成。例如，以下 `DeleteItem` 操作仅在项目具有 *RecordLabel* 属性时删除项目。

```
{
    TableName: "Music",
    Key: {
        Artist: "The Acme Band",
        SongTitle: "Look Out, World"
    },
   ConditionExpression: "attribute_exists(RecordLabel)"
}
```

------
#### [ PartiQL for DynamoDB ]

使用 PartiQL，您可以使用 `Delete` 语句通过 `ExecuteStatement` 操作删除表中的数据（一次删除一个项目）。您必须指定项目的主键值。

此表的主键包含 *Artist* 和 *SongTitle*。您必须为这些属性指定值。

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

您还可以指定操作的其他选项。以下 `DELETE` 操作只有在项目超过 11 个*奖项*时才会删除该项目。

```
DELETE FROM Music
WHERE Artist = 'Acme Band' AND SongTitle = 'PartiQL Rocks' AND Awards > 11
```

**注意**  
有关使用 `DELETE` 和 `ExecuteStatement` 的代码示例，请参阅 [PartiQL for DynamoDB Delete 语句](ql-reference.delete.md)。

------

# 关系（SQL）数据库和 DynamoDB 在删除表方面的差异
<a name="SQLtoNoSQL.RemoveTable"></a>

在 SQL 中，可使用 `DROP TABLE` 语句删除表。在 Amazon DynamoDB 中，使用 `DeleteTable` 操作。

**Topics**
+ [使用 SQL 删除表](#SQLtoNoSQL.RemoveTable.SQL)
+ [在 DynamoDB 中删除表](#SQLtoNoSQL.RemoveTable.DynamoDB)

## 使用 SQL 删除表
<a name="SQLtoNoSQL.RemoveTable.SQL"></a>

当您不再需要一个表并希望将它永久性丢弃时，您将使用 SQL 中的 `DROP TABLE` 语句。

```
DROP TABLE Music;
```

表一经删除便无法恢复。(一些关系数据库允许您撤消 `DROP TABLE` 操作，但这是一项供应商特定的功能，并未广泛实施。)

## 在 DynamoDB 中删除表
<a name="SQLtoNoSQL.RemoveTable.DynamoDB"></a>

在 DynamoDB 中，`DeleteTable` 是类似的操作。在以下示例中，表将被永久删除。

```
{
    TableName: "Music"
}
```