

 从补丁 198 开始，Amazon Redshift 将不再支持创建新的 Python UDF。现有的 Python UDF 将继续正常运行至 2026 年 6 月 30 日。有关更多信息，请参阅[博客文章](https://aws.amazon.com/blogs/big-data/amazon-redshift-python-user-defined-functions-will-reach-end-of-support-after-june-30-2026/)。

# 使用 Amazon Redshift 数据 API
<a name="data-api"></a>

Amazon Redshift 数据 API 消除了管理数据库驱动程序、连接、网络配置、数据缓冲、凭证等的需求，从而简化了对 Amazon Redshift 数据仓库的访问。您可以通过 AWS SDK，使用数据 API 操作来运行 SQL 语句。有关数据 API 操作的更多信息，请参阅 [Amazon Redshift 数据 API 参考](https://docs.aws.amazon.com/redshift-data/latest/APIReference/)。

数据 API 不需要与数据库的持久连接。相反，它提供了安全 HTTP 端点以及与 AWS 开发工具包的集成。您可以使用终端节点运行 SQL 语句，而无需管理连接。对数据 API 的调用是异步的。数据 API 可以使用存储在 AWS Secrets Manager 中的凭证或临时数据库凭证。您无需使用任何一种授权方法在 API 调用中传递密码。有关 AWS Secrets Manager 的更多信息，请参阅《AWS Secrets Manager 用户指南》**中的[什么是 AWS Secrets Manager？](https://docs.aws.amazon.com/secretsmanager/latest/userguide/intro.html) 您也可以使用 AWS IAM Identity Center 进行授权。

使用数据 API，您可以通过基于 Web 服务的应用程序（包括 AWS Lambda、Amazon SageMaker AI 笔记本和 AWS Cloud9），以编程方式访问 Amazon Redshift 数据。有关这些应用程序的更多信息，请参阅 [AWS Lambda](https://aws.amazon.com/lambda/)、[Amazon SageMaker AI](https://aws.amazon.com/sagemaker/) 和 [AWS Cloud9](https://aws.amazon.com/cloud9/)。

要了解有关数据 API 的更多信息，请参阅 *AWS 大数据博客*中的 [Get started with the Amazon Redshift Data API](https://aws.amazon.com/blogs/big-data/get-started-with-the-amazon-redshift-data-api/)。

## 使用 Amazon Redshift 数据 API
<a name="data-api-workflow"></a>

在您使用 Amazon Redshift 数据 API 之前，请查看以下步骤：

1. 确定您作为数据 API 的调用者是否获得授权。有关授权的更多信息，请参阅[授予对 Amazon Redshift 数据 API 的访问权限](data-api-access.md)。

1. 确定是否计划使用来自 Secrets Manager 的身份验证凭证、临时凭证或使用 AWS IAM Identity Center 来调用数据 API。有关更多信息，请参阅 [在调用 Amazon Redshift 数据 API 时选择数据库身份验证凭证](#data-api-calling-considerations-authentication)。

1. 如果您将 Secrets Manager 用于身份验证凭证，请设置密码。有关更多信息，请参阅 [在 AWS Secrets Manager 中存储数据库凭证](data-api-secrets.md)。

1. 查看调用数据 API 时的注意事项和限制。有关更多信息，请参阅 [调用 Amazon Redshift 数据 API 时的注意事项](#data-api-calling-considerations)。

1. 从 AWS Command Line Interface (AWS CLI)、您自己的代码中调用数据 API，或使用 Amazon Redshift 控制台中的查询编辑器。有关从 AWS CLI 进行调用的示例，请参阅[调用 Data API](data-api-calling.md)。

## 调用 Amazon Redshift 数据 API 时的注意事项
<a name="data-api-calling-considerations"></a>

调用数据 API 时，请注意以下事项：
+ Amazon Redshift 数据 API 可以访问 Amazon Redshift 预置集群和 Redshift Serverless 工作组中的数据库。有关可以使用数据 API 的 AWS 区域列表，请参阅《Amazon Web Services 一般参考》**中为 [Redshift 数据 API](https://docs.aws.amazon.com/general/latest/gr/redshift-service.html) 列出的端点。
+ 查询的最长持续时间为 24 小时。
+ 每个 Amazon Redshift 集群的最大活动查询（`STARTED` 和 `SUBMITTED` 查询）数量为 500 个。
+ 最大查询结果大小为 500 MB（gzip 压缩后）。如果调用返回的响应数据超过 500 MB，则调用将结束。
+ 查询结果的最长保留时间为 24 小时。
+ 最大查询语句大小为 100 KB。
+ 数据 API 可用于查询以下节点类型的单节点和多节点集群：
  + dc2.large
  + dc2.8xlarge
  + ra3.large
  + ra3.xlplus
  + ra3.4xlarge
  + ra3.16xlarge
+ 集群必须在基于 Amazon VPC 服务的 Virtual Private Cloud (VPC) 中。
+ 默认情况下，具有与 `ExecuteStatement` 或 `BatchExecuteStatement` API 操作运行者相同的 IAM 角色的用户可以使用 `CancelStatement`、`DescribeStatement`、`GetStatementResult`、`GetStatementResultV2` 和 `ListStatements` API 操作对同一个语句进行操作。要从另一个用户对同一 SQL 语句执行操作，该用户必须能够代入运行 SQL 语句的用户的 IAM 角色。有关如何代入角色的更多信息，请参阅[授予对 Amazon Redshift 数据 API 的访问权限](data-api-access.md)。
+ `BatchExecuteStatement` API 操作的 `Sqls` 参数中的 SQL 语句将作为单个事务运行。它们按数组的顺序连续运行。后续的 SQL 语句要等到数组中的前一条语句完成后才会开始。如果任何 SQL 语句失败，由于它们作为一个事务运行，所有工作都将回滚。
+ 在 `ExecuteStatement` 或 `BatchExecuteStatement` API 操作中使用的客户端令牌的最长保留时间为 8 小时。
+ 如果使用客户自主管理型密钥对 Amazon Redshift 预调配集群和 Redshift Serverless 工作组进行加密，则 Redshift 将创建一项授权，允许 Redshift Data API 将该密钥用于其操作。有关更多信息，请参阅 [结合使用 AWS KMS 与 Amazon Redshift Data API](data-api-kms.md)。
+ Redshift 数据 API 中的每个 API 都有每秒事务次数配额，超过该配额会对请求节流。有关配额，请参阅 [Amazon Redshift 数据 API 的配额](amazon-redshift-limits.md#data-api-quotas-account)。如果请求速率超过配额，则会返回 `ThrottlingException` 以及“HTTP 状态代码：400”。要应对节流的情况，请使用重试策略，如《AWS SDK 和工具参考指南》**中的[重试行为](https://docs.aws.amazon.com/sdkref/latest/guide/feature-retry-behavior.html)所述。在某些 AWS SDK 中，会针对节流错误自动实施这一策略。
**注意**  
在 AWS Step Functions 中，默认情况下未启用重试功能。如果您需要在 Step Functions 状态机中调用 Redshift 数据 API，请在 Redshift 数据 API 调用中包括 `ClientToken` 幂等性参数。`ClientToken` 的值需要在重试之间保持不变。在以下 `ExecuteStatement` API 请求的示例片段中，表达式 `States.ArrayGetItem(States.StringSplit($$.Execution.Id, ':'), 7)` 使用内置函数提取 `$$.Execution.Id` 的 UUID 部分，这一部分在状态机的每次执行中都是唯一的。有关更多信息，请参阅《AWS Step Functions 开发人员指南》**中的[内置函数](https://docs.aws.amazon.com/step-functions/latest/dg/amazon-states-language-intrinsic-functions.html)。  

  ```
  {
    "Database": "dev",
    "Sql": "select 1;",
    "ClusterIdentifier": "MyCluster",
    "ClientToken.$": "States.ArrayGetItem(States.StringSplit($$.Execution.Id, ':'), 7)"
  }
  ```

## 在调用 Amazon Redshift 数据 API 时选择数据库身份验证凭证
<a name="data-api-calling-considerations-authentication"></a>

当您调用数据 API 时，您对某些 API 操作使用以下身份验证方法之一。每种方法都需要不同的参数组合。

**AWS IAM Identity Center**  
在 AWS IAM Identity Center 中注册的单点登录用户可以访问数据 API。有关设置 IAM Identity Center 的步骤的信息，请参阅[将数据 API 与可信身份传播结合使用](data-api-trusted-identity-propagation.md)。

**AWS Secrets Manager**  
使用此方法，提供存储在 AWS Secrets Manager 中密钥的 `secret-arn`，其中包括了 `username` 和 `password`。指定的密钥包含用于连接到您指定的 `database` 的凭证。在连接到集群时，如果您提供了集群标识符（`dbClusterIdentifier`），则还可以提供数据库名称，该名称必须与密钥中存储的集群标识符相匹配。在连接到无服务器工作组时，也要提供数据库名称。有关更多信息，请参阅 [在 AWS Secrets Manager 中存储数据库凭证](data-api-secrets.md)。  
使用此方法，您还可以提供 `region` 值，该值指定您的数据所在的 AWS 区域。

**临时凭证**  
使用此方法时，请选择以下选项之一：  
+ 在连接到无服务器工作组时，需指定工作组名称和数据库名称。数据库用户名派生自 IAM 身份。例如，`arn:iam::123456789012:user:foo` 具有数据库用户名 `IAM:foo`。此外，需具有调用 `redshift-serverless:GetCredentials` 操作的权限。
+ 以 IAM 身份连接到集群时，需要指定集群标识符和数据库名称。数据库用户名派生自 IAM 身份。例如，`arn:iam::123456789012:user:foo` 具有数据库用户名 `IAM:foo`。此外，需具有调用 `redshift:GetClusterCredentialsWithIAM` 操作的权限。
+ 以数据库用户的身份连接到机群时，需要指定集群标识符、数据库名称和数据库用户名。此外，需具有调用 `redshift:GetClusterCredentials` 操作的权限。有关使用此方法进行连接时如何加入数据库组的信息，请参阅[连接到集群时加入数据库组](data-api-dbgroups.md)。
使用此方法，您还可以提供 `region` 值，该值指定您的数据所在的 AWS 区域。

## 调用 Amazon Redshift 数据 API 时映射 JDBC 数据类型
<a name="data-api-calling-considerations-jdbc"></a>

 下表将 Java 数据库连接 (JDBC) 数据类型映射到您在数据 API 调用中指定的数据类型。


****  

|  JDBC 数据类型  |  Data API 数据类型  | 
| --- | --- | 
| `INTEGER, SMALLINT, BIGINT` | `LONG` | 
| `FLOAT, REAL, DOUBLE` | `DOUBLE` | 
| `DECIMAL` | `STRING` | 
| `BOOLEAN, BIT` | `BOOLEAN` | 
| `BLOB, BINARY, LONGVARBINARY` | `BLOB` | 
| `VARBINARY` | `STRING` | 
| `CLOB` | `STRING` | 
| 其他类型（包括与日期和时间有关的类型） | `STRING` | 

字符串值将传递到 Amazon Redshift 数据库并隐式转换为数据库数据类型。

**注意**  
目前，数据 API 不支持通用唯一标识符 (UUID) 的数组。

## 在调用 Amazon Redshift 数据 API 时运行带有参数的 SQL 语句
<a name="data-api-calling-considerations-parameters"></a>

您可以通过使用 SQL 语句部分的参数调用数据 API 操作来控制提交到数据库引擎的 SQL 文本。命名参数提供了一种灵活的方式来传入参数，而无需在 SQL 文本中对参数进行硬编码。它们可以帮助您重复使用 SQL 文本并避免 SQL 注入问题。

以下示例显示 `execute-statement` 或 `batch-execute-statement` AWS CLI 命令的 `parameters` 字段的命名参数。

```
--parameters "[{\"name\": \"id\", \"value\": \"1\"},{\"name\": \"address\", \"value\": \"Seattle\"}]"
```

使用命名参数时，请注意以下事项：
+ 命名参数只能用于替换 SQL 语句中的值。
  + 您可以替换 INSERT 语句中的值，例如 `INSERT INTO mytable VALUES(:val1)`。

    命名参数可以按任意顺序排列，并且参数可以在 SQL 文本中多次使用。前面示例中显示的参数选项，值 `1` 和 `Seattle` 插入到表列 `id` 和 `address` 中。在 SQL 文本中，您可以按如下方式指定命名参数：

    ```
    --sql "insert into mytable values (:id, :address)"
    ```
  + 您可以替换条件子句中的值，例如 `WHERE attr >= :val1`、`WHERE attr BETWEEN :val1 AND :val2` 和 `HAVING COUNT(attr) > :val`。
  + 您无法替换 SQL 语句中的列名，例如 `SELECT column-name`、`ORDER BY column-name` 或 `GROUP BY column-name`。

    例如，以下 SELECT 语句将失败，出现语法无效错误。

    ```
    --sql "SELECT :colname, FROM event" --parameters "[{\"name\": \"colname\", \"value\": \"eventname\"}]"
    ```

    如果您说明（`describe-statement` 操作）语句有语法错误，则返回的 `QueryString` 不会用列名代替参数（`"QueryString": "SELECT :colname, FROM event"`），并且会报告错误（错误：在 \\"FROM\\"\\ 处或附近出现语法错误 \\n 位置：12）。
  + 您无法替换聚合函数中的列名，例如 `COUNT(column-name)`、`AVG(column-name)` 或 `SUM(column-name)`。
  + 您无法替换 JOIN 子句中的列名。
+ SQL 运行时，数据将隐式转换为数据类型。有关数据类型转换的更多信息，请参阅《Amazon Redshift 数据库开发人员指南》**中的[数据类型](https://docs.aws.amazon.com/redshift/latest/dg/c_Supported_data_types.html)。
+ 您不能将值设置为 NULL。数据 API 将其解释为文本字符串 `NULL`。以下示例将 `id` 替换为文本字符串 `null`。不是 SQL NULL 值。

  ```
  --parameters "[{\"name\": \"id\", \"value\": \"null\"}]"
  ```
+ 无法设置零长度值。数据 API SQL 语句失败。下面的示例尝试设置 `id` 长度值为零，导致 SQL 语句失败。

  ```
  --parameters "[{\"name\": \"id\", \"value\": \"\"}]"
  ```
+ 不能在带有参数的 SQL 语句中设置表名。数据 API 遵循 JDBC `PreparedStatement` 的规则。
+ `describe-statement` 操作的输出返回 SQL 语句的查询参数。
+ 仅 `execute-statement` 和 `batch-execute-statement` 操作支持带有参数的 SQL 语句。使用 `batch-execute-statement` 时，参数将在批处理中的所有 SQL 语句之间共享。每个 SQL 语句都可以引用所提供参数的子集，但每个参数都必须由至少一个 SQL 语句使用。

## 在调用 Amazon Redshift 数据 API 时运行带有幂等性令牌的 SQL 语句
<a name="data-api-calling-considerations-idempotency"></a>

当您发出变更 API 请求时，该请求通常会在操作的异步工作流完成之前返回结果。即使请求已经返回结果，操作在完成之前也可能会超时或遇到其他服务器问题。这样就很难确定请求是否成功，并且会导致进行多次重试以确保操作成功完成。但是，如果原始请求和后续重试成功，则会多次完成操作。这意味着您可能会更新比预期更多的资源。

*幂等性*确保 API 请求完成不超过一次。对于幂等性请求，如果原始请求成功完成，则后续重试也会成功完成，而不会执行任何后续操作。数据 API `ExecuteStatement` 和 `BatchExecuteStatement` 操作具有可选的 `ClientToken` 幂等性参数。`ClientToken` 在 8 小时后过期。

**重要**  
如果您从 AWS SDK 调用 `ExecuteStatement` 和 `BatchExecuteStatement` 操作，它会自动生成客户端令牌以供重试时使用。在这种情况下，我们不建议将 `client-token` 参数与 `ExecuteStatement` 和 `BatchExecuteStatement` 操作一起使用。查看 CloudTrail 日志以查看 `ClientToken`。有关 CloudTrail 日志示例，请参阅 [Amazon Redshift 数据 API 示例](logging-with-cloudtrail.md#data-api-cloudtrail)。

以下 `execute-statement` AWS CLI 命令说明了幂等性的可选 `client-token` 参数。

```
aws redshift-data execute-statement 
    --secret-arn arn:aws:secretsmanager:us-west-2:123456789012:secret:myuser-secret-hKgPWn 
    --cluster-identifier mycluster-test 
    --sql "select * from stl_query limit 1" 
    --database dev 
    --client-token b855dced-259b-444c-bc7b-d3e8e33f94g1
```

下表显示了幂等性 API 请求可能获得的一些常见响应，并提供了重试建议。


| 响应 | 建议 | 评论 | 
| --- | --- | --- | 
| 200（正常） | 不重试 | 原始请求成功完成。成功返回任何后续重试。 | 
| 400 系列响应代码  | 不重试 | 请求存在问题，原因如下：[See the AWS documentation website for more details](http://docs.aws.amazon.com/zh_cn/redshift/latest/mgmt/data-api.html)<br />如果请求涉及正在改变状态的资源，则重试请求可能会成功。 | 
| 500 系列响应代码  | 重试 | 该错误是由 AWS 服务器端问题引起，通常是暂时性的。使用适当的退避策略重复发出请求。 | 

有关 Amazon Redshift 响应代码的信息，请参阅《Amazon Redshift API 参考》**中的[常见错误](https://docs.aws.amazon.com/redshift/latest/APIReference/CommonErrors.html)。

## 在调用 Amazon Redshift 数据 API 时运行带有会话重用的 SQL 语句
<a name="data-api-calling-considerations-session-reuse"></a>

当您发出 API 请求来运行 SQL 语句时，在其中运行 SQL 的会话通常在 SQL 完成后终止。为了在指定的秒数内使会话保持活动状态，数据 API `ExecuteStatement` 和 `BatchExecuteStatement` 操作具有可选的 `SessionKeepAliveSeconds` 参数。`SessionId` 响应字段包含会话的身份，随后可以在后续 `ExecuteStatement` 和 `BatchExecuteStatement` 操作中使用该身份。在后续调用中，可以指定另一个 `SessionKeepAliveSeconds` 来更改空闲超时时间。如果未更改 `SessionKeepAliveSeconds`，则会保留初始空闲超时设置。使用会话重用时，请考虑以下事项：
+ `SessionKeepAliveSeconds` 的最大值为 24 小时。
+ 会话最多可持续 24 小时。24 小时后，会话将被强制关闭，正在进行的查询将被终止。
+ 每个 Amazon Redshift 集群或 Redshift Serverless 工作组的最大会话数为 500 个。
+ 在会话中，一次只能运行一个查询。您需要等到查询完成后，才能在同一个会话中运行下一个查询。也就是说，不能在提供的会话中并行运行查询。
+ 数据 API 无法对给定会话的查询进行排队。

要检索调用 `ExecuteStatement` 和 `BatchExecuteStatement` 操作时所使用的 `SessionId`，请调用 `DescribeStatement` 和 `ListStatements` 操作。

以下示例演示如何使用 `SessionKeepAliveSeconds` 和 `SessionId` 参数来使会话保持活动状态并重用。首先，在可选 `session-keep-alive-seconds` 参数设置为 `2` 的情况下调用 `execute-statement` AWS CLI 命令。

```
aws redshift-data execute-statement 
    --session-keep-alive-seconds 2 
    --sql "select 1" 
    --database dev 
    --workgroup-name mywg
```

响应将包含会话标识符。

```
{
    "WorkgroupName": "mywg",
    "CreatedAt": 1703022996.436,
    "Database": "dev",
    "DbUser": "awsuser",
    "Id": "07c5ffea-76d6-4786-b62c-4fe3ef529680",
    "SessionId": "5a254dc6-4fc2-4203-87a8-551155432ee4"
}
```

然后，使用从第一个调用返回的 `SessionId` 来调用 `execute-statement` AWS CLI 命令。或者，指定将 `session-keep-alive-seconds` 参数设置为 `10` 以更改空闲超时值。

```
aws redshift-data execute-statement 
    --sql "select 1" 
    --session-id 5a254dc6-4fc2-4203-87a8-551155432ee4
    --session-keep-alive-seconds 10
```

## 获取 SQL 语句的结果
<a name="data-api-calling-considerations-result-format"></a>

根据结果格式，您可以使用不同的数据 API 操作来获取 SQL 结果。在调用 `ExecuteStatement` 和 `BatchExecuteStatement` 操作时，可以指定结果的格式是 JSON 还是 CSV。如果未指定，则默认格式为 JSON。要检索 JSON 结果，请使用 `GetStatementResult` 操作。要检索 CSV 结果，请使用 `GetStatementResultV2` 操作。

以 JSON 格式返回的结果是包含有关每列的元数据的记录。每条记录都是 JSON 格式。例如，来自 `GetStatementResult` 的响应与以下内容相似：

```
{
   "ColumnMetadata": [ 
      { 
         "isCaseSensitive": false,
         "isCurrency": false,
         "isSigned": true,
         "label": "?column?",
         "name": "?column?",
         "nullable": 1,
         "precision": 10,
         "scale": 0,
         "schemaName": "",
         "tableName": "",
         "typeName": "int4",
         "length": 0
      }
   ],
   "NextToken": "{{<token>}}",
   "Records": [
        [
            {
                "longValue": 1
            }
        ]
    ],
   "TotalNumRows": {{<number>}}
}
```

以 CSV 格式返回的结果是包含有关每列的元数据的记录。结果以 1 MB 的分块形式返回，其中每个分块能够以 CSV 格式存储任意数量的行。每个请求最多返回 15 MB 的结果。如果结果大于 15 MB，则返回下一页令牌以继续检索结果。例如，来自 `GetStatementResultV2` 的响应与以下内容相似：

```
{
    "ColumnMetadata": [
        {
            "isCaseSensitive": false,
            "isCurrency": false,
            "isSigned": true,
            "label": "?column?",
            "name": "?column?",
            "nullable": 1,
            "precision": 10,
            "scale": 0,
            "schemaName": "",
            "tableName": "",
            "typeName": "int4",
            "length": 0
        },
        {
            "isCaseSensitive": false,
            "isCurrency": false,
            "isSigned": true,
            "label": "?column?",
            "name": "?column?",
            "nullable": 1,
            "precision": 10,
            "scale": 0,
            "schemaName": "",
            "tableName": "",
            "typeName": "int4",
            "length": 0
        },
        {
            "isCaseSensitive": false,
            "isCurrency": false,
            "isSigned": true,
            "label": "?column?",
            "name": "?column?",
            "nullable": 1,
            "precision": 10,
            "scale": 0,
            "schemaName": "",
            "tableName": "",
            "typeName": "int4",
            "length": 0
        }
    ],
    "NextToken": "{{<token>}}",
    "Records": [
        [
            {
                "CSVRecords":"1,2,3\r\n4,5,6\r\n7,8,9\rn, .... 1MB" // First 1MB Chunk
            },
            {
                "CSVRecords":"1025,1026,1027\r\n1028,1029,1030\r\n....2MB" // Second 1MB chunk
            }
            ...
        ]
    ],
    "ResultFormat" : "CSV",
    "TotalNumRows": {{<number>}}
}
```