关于 redshift-api
为 Amazon Redshift Data API 查询与管理操作提供指南和脚本的技能,适用于需要通过 Data API 执行 SQL 的数据工作流。它将异步提交、状态轮询和分页取回结果串联起来,也覆盖目录浏览、批量语句与取消操作。
主要功能
- 01提交 SQL 并轮询执行状态
- 02分页获取并解码查询结果
- 03按 ID 恢复语句并取消运行
- 04在事务中执行多条语句
- 05浏览数据库、模式、表和列
适用场景
- 01运行并获取大型查询的分页结果
- 02查询超时后通过语句 ID 恢复
- 03检查表结构或批量执行事务语句
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ anthropics/ claude-tag-plugins --skill redshift-api安装后在 Claude Code 中输入/redshift-api确认已加载。
附带文件references/api.mdscripts/rs_query.sh
详细介绍
在 Amazon Redshift Data API 中,每次调用都是向 https://redshift-data.<region>.amazonaws.com/ 发送 POST 请求,并带上
Content-Type: application/x-amz-json-1.1 和 X-Amz-Target: RedshiftData.<Action>——它没有 REST 风格的路径。该 API 完全采用异步方式:提交语句,获取 Id,轮询
DescribeStatement 直到完成,然后通过 GetStatementResult 分页获取结果——
scripts/rs_query.sh(操作 1)会替你完成这一流程。相同的调用适用于预置集群和 Serverless;只有连接目标字段不同。
请求设置
身份验证由运行时处理——对此 API 的请求会使用为工作区配置的凭证进行签名,因此无需进行任何设置。请勿尝试获取 AWS 密钥或自行对请求签名。如果持续出现 AccessDeniedException,说明尚未为此工作区配置凭证——应报告这一情况,而不是排查身份验证问题。
有两项实际必需的配置:
1. 区域——它是端点主机名的一部分:
export AWS_DEFAULT_REGION="us-east-1" # the region your cluster / workgroup is in
2. 连接目标——Data API 要连接的集群/工作组和数据库。选择一种方式,并将对应的 JSON 字段填入 RS_TARGET;以下示例会将其合并到每个请求正文中:
- Serverless——传入
WorkgroupName。配置的身份会映射到数据库用户。 最简单。 - 预置集群,临时凭证——传入
ClusterIdentifier和DbUser。Data API 会在后台解析数据库凭证。 - 预置集群或 Serverless,使用 Secrets Manager——传入指向包含数据库登录信息的密钥的
SecretArn。
根据实际情况设置一次:
export RS_DATABASE="dev"
# Serverless:
export RS_TARGET='{"WorkgroupName": "my-workgroup"}'
# — or provisioned + temp creds:
# export RS_TARGET='{"ClusterIdentifier": "my-cluster", "DbUser": "my_user"}'
# — or either + Secrets Manager:
# export RS_TARGET='{"ClusterIdentifier": "my-cluster", "SecretArn": "arn:aws:secretsmanager:us-east-1:123456789012:secret:rs-creds-AbCdEf"}'
下文使用的辅助函数。 一个函数封装了端点、请求头和操作名称。Authorization 请求头是占位符——运行时会将其替换为真实签名。
rsapi() {
local action="$1"
curl -sS "https://redshift-data.${AWS_DEFAULT_REGION}.amazonaws.com/" \
-H "Content-Type: application/x-amz-json-1.1" \
-H "X-Amz-Target: RedshiftData.${action}" \
-H "Authorization: placeholder" \
-d "${2:?rsapi needs a JSON body as the second argument}"
}
基本检查——列出数据库。200 响应中包含 Databases 数组,表明工作区配置正常且连接目标正确。错误信息会指出失败的环节。
rsapi ListDatabases "$(jq -n --argjson t "$RS_TARGET" --arg db "$RS_DATABASE" \
'$t + {Database: $db}')" | jq .
核心操作
每项连接数据库的操作都使用相同的合并目标正文——
$t + {Database: $db, ...}。错误会以 {"__type": "<Exception>", "message": "..."} 的形式返回,而不是预期的结构;对于任何调用,如果顶层字段(Id、Status、Records 等)缺失,就说明收到的是错误封装——打印错误并停止。
1. 运行查询(scripts/rs_query.sh)
通过捆绑的脚本运行 SQL(路径相对于此技能目录):脚本使用
ExecuteStatement 提交语句,轮询 DescribeStatement 直到进入终止状态,通过 NextToken 对 GetStatementResult 的结果分页,并解码带类型的单键单元格对象。
scripts/rs_query.sh \
'SELECT event_name, COUNT(*) AS n FROM public.events
WHERE event_date >= :start GROUP BY 1 ORDER BY 2 DESC LIMIT 20' \
--param start=2024-01-01 --name top-events
- SQL 是一个参数(也可通过标准输入传入)。实例相关配置来自上文的
AWS_DEFAULT_REGION/RS_TARGET/RS_DATABASE;--database可覆盖数据库。 --param NAME=VALUE(可重复使用)用于绑定:NAME占位符——值始终是字符串,由数据库进行类型转换。--name用于设置StatementName,让查询显示在ListStatements中。--max-rows N限制获取的行数(默认为 10000,0= 全部);--json会为每行输出一个 JSON 对象,而不是带表头的 TSV。语句 ID、状态、耗时和行数会输出到 stderr。- 退出码:
0表示成功;1表示提交失败或 SQL 状态为FAILED/ABORTED(API 自身的消息会输出到 stderr);2表示等待超过--max-wait秒后放弃(默认为 600)——语句 ID 会输出到 stderr;使用操作 2 恢复执行。
如果脚本报错,请阅读脚本——它只是普通的 curl + jq——并参照 references/api.md 进行排查。
如需使用 BatchExecuteStatement 和子语句结果、复用会话(SessionKeepAliveSeconds /
SessionId)、ResultFormat: CSV、取消操作或浏览目录,请使用下方的操作。
2. 按 ID 恢复语句(DescribeStatement → GetStatementResult)
当脚本以状态码 2(超时)退出,或你从其他地方获取了语句 ID 时,可直接轮询并获取结果:
rsapi DescribeStatement "$(jq -n --arg id "$ID" '{Id: $id}')" \
| jq '{Status, Duration, ResultRows, HasResultSet, Error}'
rsapi GetStatementResult "$(jq -n --arg id "$ID" '{Id: $id}')" \
| jq -r '.Records[]? | [.[] | if .isNull then null else to_entries[0].value end] | @tsv'
Status∈SUBMITTED、PICKED、STARTED、FINISHED、FAILED、ABORTED。只有FINISHED且HasResultSet: true时才有行;FAILED会在.Error中包含 SQL 错误。Duration的单位是纳秒。- 结果单元格是带有一个键的类型化对象(参见“错误处理”中的注意事项);列名和类型位于第一页的
.ColumnMetadata中。后续页面通过NextToken获取——没有页面大小设置项;DescribeStatement.ResultRows会预先给出总行数。
3. 取消正在运行的语句(CancelStatement)
rsapi CancelStatement "$(jq -n --arg id "$ID" '{Id: $id}')" | jq .
# {"Status": true} on success — best-effort, check DescribeStatement to confirm.
4. 在一次调用中运行多条语句(BatchExecuteStatement)
所有语句在同一事务中运行——要么全部提交,要么全部回滚。
rsapi BatchExecuteStatement "$(jq -n --argjson t "$RS_TARGET" --arg db "$RS_DATABASE" '$t + {
Database: $db,
Sqls: ["CREATE TEMP TABLE tmp AS SELECT 1 AS x", "SELECT * FROM tmp"]
}')" | jq '{Id}'
对父级 Id 调用 DescribeStatement 会返回一个 SubStatements[] 数组。每条子语句都有自己的 Id(父级 ID 后缀为 :1、:2、……)、Status 和 HasResultSet——分别调用各自的 GetStatementResult 获取子语句结果。
5. 列出最近的语句(ListStatements)
rsapi ListStatements '{"MaxResults": 20, "Status": "ALL"}' \
| jq '.Statements[] | {Id, StatementName, Status, QueryString: (.QueryString[0:80]), CreatedAt}'
Status 筛选条件:SUBMITTED、PICKED、STARTED、FINISHED、FAILED、ABORTED、ALL——如果省略该参数,只会列出已完成的语句。MaxResults 为 0–100。RoleLevel 默认为 true(包括任何使用相同 IAM 角色的人的语句);设为 false 可仅查看当前会话的语句。
6. 浏览目录(ListDatabases / ListSchemas / ListTables / DescribeTable)
这四项操作都使用合并后的目标请求体。模式使用 SQL LIKE 通配符(%、_)。
ListDatabases—Databases[](字符串)ListSchemas—SchemaPattern(可选)—Schemas[](字符串)ListTables—SchemaPattern、TablePattern—Tables[] {schema, name, type}—type∈TABLE/VIEW/SYSTEM TABLE/GLOBAL TEMPORARY/LOCAL TEMPORARY/ALIAS/SYNONYMDescribeTable—Schema、Table—ColumnList[] {name, typeName, nullable, length, precision}
rsapi ListTables "$(jq -n --argjson t "$RS_TARGET" --arg db "$RS_DATABASE" \
'$t + {Database: $db, SchemaPattern: "public", TablePattern: "ev%"}')" | jq '.Tables'
JSON 字段名采用 PascalCase(WorkgroupName,而非 workgroup-name)。这四项操作都支持分页(NextToken)。各操作请求体的完整格式请参见 references/api.md。
分页
GetStatementResult、ListStatements、ListDatabases、ListSchemas、ListTables 和
DescribeTable 都采用相同的分页方式:如果还有更多结果,响应中会包含 NextToken;在下一次请求体中将其作为 NextToken 传回。没有该字段时即停止。
速率限制
- 活动语句 — 每个集群或工作组最多允许 500 条活动语句(
SUBMITTED/STARTED)。超出后,提交会失败并返回ActiveStatementsExceededException。 - 结果大小 — 每条语句最多 500 MB(gzip 压缩后),每行最多 64 KB。结果过大时会失败;请添加
LIMIT,或使用UNLOAD ... TO 's3://...'。 - 结果保留时间 — 24 小时;此后,
GetStatementResult会返回ResourceNotFoundException。 - 语句时长 — 最长 24 小时。查询字符串 — 最长 100 KB。
- API 速率 — 每个账户/区域的 TPS 配额固定,无法调整:
DescribeStatement为 100,ExecuteStatement为 30,GetStatementResult为 20,BatchExecuteStatement为 20;而CancelStatement、ListStatements、ListDatabases、ListSchemas、ListTables、DescribeTable仅为 3 TPS。超出配额会返回ThrottlingException(HTTP 400)——请降低请求频率,不要在紧密循环中轮询。
错误处理
错误以 {"__type": "<Exception>", "message": "..."} 的形式返回(HTTP 400/403/500)。__type
字段是判别字段。
ValidationException(400) — 参数错误。常见情况:同时传入ClusterIdentifier和WorkgroupName,或两者都未传入;缺少Database;字段大小写错误。ActiveStatementsExceededException(400) — 正在执行的语句过多。ListStatements{"Status":"STARTED"}会显示正在运行的语句。ActiveSessionsExceededException(400) — 打开的会话超过 500 个。不要再传入SessionKeepAliveSeconds,或等待空闲会话过期。ExecuteStatementException(500) — 数据库收到请求前提交就已失败——集群或工作组名称错误、集群不可达、DbUser错误。检查RS_TARGET。ResourceNotFoundException(400) — 语句 ID 未知或已超过 24 h。BatchExecuteStatementException(500) — 批次中的某条语句失败;整个事务已回滚。检查SubStatements[].Error。DatabaseConnectionException/QueryTimeoutException— 目录调用无法连接数据库或超时。检查目标是否正常运行;然后重试。AccessDeniedException(403) — 凭证需要对集群/工作组 ARN 具有redshift-data:*权限,此外还需根据连接模式具有redshift:GetClusterCredentials/redshift-serverless:GetCredentials/secretsmanager:GetSecretValue权限。请说明缺少哪项权限。InternalServerException(500) — 除非传入ClientToken,否则ExecuteStatement不具备幂等性——重试写入前先检查ListStatements。DescribeStatement中出现Status: FAILED— 提交后 SQL 执行失败。读取.Error获取 SQL 错误信息。
两个易错之处:
ExecuteStatement返回 200 ≠ 查询成功。 SQL 错误只会在之后DescribeStatement中显示为Status: FAILED。获取结果前务必先轮询状态。- 单元格值是带类型的单键对象,而不是裸值。
longValue是 JSON 数字,isNull: true则是另一种独立结构。简单读取.value会得到空值,而在带类型的键之间串联 jq//会在遇到false/0时出错。请使用to_entries[0].value。
深入了解
references/api.md 包含完整目录——每个操作的 PascalCase 请求/响应结构(用于原始 HTTP)、SqlParameter 绑定格式、ColumnMetadata 字段、批次的 SubStatementData、会话复用(SessionKeepAliveSeconds / SessionId)以及配额表。需要使用上述内容未涵盖的操作,或了解原始 HTTP 请求体的精确结构时,请阅读该文档。