mcpField
B
bigquery-api

bigquery-api

github.com/anthropics数据与数据库7438 次安装3 周前更新
代码仓库

关于 bigquery-api

通过 curl 使用 BigQuery REST API 执行 SQL 和查看数据的技能,无需 SDK。它提供查询脚本,并介绍作业、数据集、表、架构及结果分页。

主要功能

  1. 01执行 SQL 查询
  2. 02提交并监控作业
  3. 03列出数据集和表
  4. 04查看架构并预览行
  5. 05对查询结果分页

适用场景

  1. 01使用 SQL 查询 BigQuery 数据
  2. 02检查表架构并查看样例行
  3. 03监控或取消查询作业

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/anthropics/claude-tag-plugins --skill bigquery-api

安装后在 Claude Code 中输入/bigquery-api确认已加载。

附带文件references/api.mdscripts/bq_query.sh

详细介绍

BigQuery 的 REST API(bigquery.googleapis.com/bigquery/v2)让你可以直接使用普通的 curl 运行 SQL、检查作业,以及浏览数据集和表架构,无需 SDK。

核心概念是作业。每个查询都会作为作业在一个项目中运行(费用计入该项目,但数据不一定存储在其中)。在底层,查询会以两种方式之一运行——scripts/bq_query.sh(操作 1)会为你处理这些流程:

  • 同步(jobs.query)——发送一个 POST 请求,最多阻塞至超时;如果查询及时完成,则直接返回行数据。
  • 异步(jobs.insert → jobs.get → jobs.getQueryResults)——提交作业、轮询,然后分页获取结果。直接使用此方式来指定目标表、BATCH 优先级,或执行加载/提取/复制作业。

其余操作(数据集、表、架构)都是简单的 GET 请求。

请求设置

认证由运行时处理——凭据会注入发送到此 API 的请求中,因此无需进行任何设置。请勿尝试创建、生成、刷新或验证令牌或密钥。凭据变量仅用于确保请求格式正确;如果某个变量未设置,请将其设为任意占位值。持续出现 401/403 错误意味着此工作区未配置凭据——请报告此问题,而不是排查认证故障。

每个请求都带有 Authorization: Bearer ...,并以计费项目为根:

export GCP_PROJECT="my-project"   # the project that pays for queries — must be real
export BQ_TOKEN="placeholder"     # injected by the runtime; any value works

定义一个辅助函数,避免在每次调用时重复填写基础 URL 和认证标头:

export BQ="https://bigquery.googleapis.com/bigquery/v2/projects/${GCP_PROJECT}"
bq_curl() { curl -sS "$@" -H "Authorization: Bearer ${BQ_TOKEN}"; }

完整性检查——确认项目正确,并确认工作区已完成配置:

bq_curl "${BQ}/datasets?maxResults=1" | jq .
# 200 with a "datasets" array on success (the key is omitted entirely when the project
# has no datasets — that's still a success); 401/403 otherwise.

核心操作

1. 运行查询(scripts/bq_query.sh)

通过捆绑的脚本运行 SQL(路径相对于此技能目录):脚本会提交 查询,持续轮询直至完成,并在整个过程中传递 location;随后分页获取所有结果页, 并解码标量列的 f/v 单元格编码(嵌套/重复列会以原始 f/v JSON 形式输出——如果需要将其扁平化,请使用 jq 后处理)。

scripts/bq_query.sh \
  'SELECT name, SUM(number) AS total
   FROM `bigquery-public-data.usa_names.usa_1910_current`
   WHERE state = @state GROUP BY name ORDER BY total DESC LIMIT 10' \
  --param state=STRING:CA --max-gb 5
  • SQL 作为一个参数传入(用单引号括起来,以免 shell 处理反引号括起的表名),也可以通过标准输入传入。 实例的具体配置来自上述 GCP_PROJECT/BQ_TOKEN;--project 可覆盖计费项目。
  • --param NAME=TYPE:VALUE(可重复使用)可发送具名查询参数——建议使用此方式,而不是 将值直接插入 SQL 字符串。
  • --dry-run 会显示查询运行时将扫描的字节数,但不会实际运行查询;--max-gb N 会使查询 在扫描量超过 N GiB 时失败。
  • --max-rows N 会限制获取的行数(默认值为 10000,0 = 全部);--json 会为每一行输出一个 JSON 对象,而不是带表头的 TSV。作业 ID、扫描字节数和行数会输出到 stderr。
  • 退出码:0 表示成功;1 表示请求或查询失败(API 错误信息输出到 stderr);2 表示在等待 --max-wait 秒(默认值为 600)后放弃等待——作业 ID 会输出到 stderr;请使用下面的端点轮询作业。

如果脚本出错,请阅读脚本——它只是普通的 curl + jq——并参考 references/api.md 进行排查。 对于数组/结构体参数、目标表或写入处置方式、BATCH 优先级,或 非查询作业(加载/提取/复制),请直接使用 jobs.insert(下一个操作)。

2. 直接提交作业(jobs.insert → jobs.get)

当你需要指定目标表、写入处置方式、BATCH 优先级,或需要提交非查询作业(加载/提取/复制)时,请自行提交作业并轮询。POST ${BQ}/jobs 会立即返回一个 jobReference:

JOB=$(bq_curl -X POST "${BQ}/jobs" -H "Content-Type: application/json" \
  -d '{"configuration": {"query": {"query": "SELECT ...", "useLegacySql": false}}}')
JOB_ID=$(jq -r '.jobReference.jobId // empty' <<<"$JOB")
LOCATION=$(jq -r '.jobReference.location // empty' <<<"$JOB")

然后轮询 GET ${BQ}/jobs/${JOB_ID}?location=${LOCATION},直到 .status.state 为 DONE——两次调用之间稍作等待,并限制循环次数(scripts/bq_query.sh 是参考实现)。完整的 configuration.query 请求体——目标表、写入处置方式、maximumBytesBilled、优先级、参数——见 references/api.md 的 Query job configuration 一节。

  • 如果返回的 JOB_ID 为空,说明插入操作本身失败;请显示 .error,不要轮询。
  • 轮询时始终传入 location——作业会固定在其运行所在的位置,省略它可能会导致非 US 数据集返回 404。
  • DONE 状态的作业仍可能失败:获取结果前请检查 .status.errorResult。
  • 使用 GET ${BQ}/queries/${JOB_ID}?location=${LOCATION}&maxResults=1000 获取查询作业的行——单元格按架构顺序以 {"f": [{"v": "..."}]} 的形式返回(列名位于 .schema.fields[].name);后续页面由 .pageToken 指示(参见 Pagination)。
3. 取消正在运行的作业
bq_curl -X POST "${BQ}/jobs/${JOB_ID}/cancel?location=${LOCATION}" | jq '.job.status // .error'

取消操作尽力而为;请轮询 jobs.get 确认。

4. 列出最近的作业
bq_curl "${BQ}/jobs?maxResults=20&projection=full&allUsers=false&stateFilter=done" \
  | jq '.jobs[]? | {id: .jobReference.jobId, state: .status.state, query: (.configuration.query.query // "" | .[0:80]), bytes: .statistics.query.totalBytesProcessed}'
5. 列出数据集
bq_curl "${BQ}/datasets?maxResults=100" \
  | jq '.datasets[]? | {id: .datasetReference.datasetId, location}'

传入 ?all=true 以包含隐藏数据集。若要列出其他项目的数据集,请替换 URL 中的项目(你需要在那里拥有 bigquery.datasets.get 权限)。

6. 列出数据集中的表
DATASET="my_dataset"
bq_curl "${BQ}/datasets/${DATASET}/tables?maxResults=100" \
  | jq '.tables[]? | {id: .tableReference.tableId, type, creationTime}'

type 可以是 TABLE、VIEW、EXTERNAL、MATERIALIZED_VIEW 或 SNAPSHOT。

7. 获取表的架构和大小
TABLE="events"
bq_curl "${BQ}/datasets/${DATASET}/tables/${TABLE}" \
  | jq '{rows: .numRows, bytes: .numBytes, partitioning: .timePartitioning, schema: [.schema.fields[]? | {name, type, mode}]}'

嵌套列会以 type: "RECORD" 的形式出现,并带有自己的 fields[]——如需完整结构,请递归处理。

8. 不执行查询即可预览表行(tabledata.list)

直接从存储中读取行——无需查询作业,也不会产生扫描字节费用。

bq_curl "${BQ}/datasets/${DATASET}/tables/${TABLE}/data?maxResults=10" \
  | jq '.rows[]?.f | map(.v)'

分页

所有列表类端点都采用相同的方式:有更多内容时,响应会携带一个令牌;在下一次调用时将其作为 ?pageToken= 传回。当该字段不存在时停止。maxResults 限制单页结果数;实际的 API 上限取决于大小(每个 tabledata.list 页面约 10 MB,每个 getQueryResults 页面约 20 MB),而非固定行数——随附脚本默认每页 1000 行。

响应字段名称并不统一——请确认端点返回的是哪个字段:

  • pageToken — jobs.query、jobs.getQueryResults、tabledata.list。
  • nextPageToken — datasets.list、tables.list、jobs.list、routines.list、models.list。

读取 datasets.list 响应中的 .pageToken 会静默返回 null,导致你只能获取一页。

查询结果还有一点需要注意:jobs.query 和 jobs.getQueryResults 还会返回 totalRows,即使单页结果更少,它也表示完整的行数——请用它设置进度条的规模,而不要将其用作停止条件。

速率限制与配额

BigQuery 限制的是项目配额,而非单个请求的速率。你可能遇到的限制如下:

  • 并发查询:BigQuery 决定同时运行的查询数量(动态并发),其余查询会排队——每个项目、每个区域最多可排队 1,000 个交互式查询。超过此数量后,提交会因 quotaExceeded / jobRateLimitExceeded 而失败。
  • API 请求:大多数方法对每位用户的每种方法限制为每秒约 100 个请求(jobs.get 和 tabledata.list 允许更高频率)——轮询时请使用 sleep,不要紧密循环。
  • 按需扫描字节数和槽位时间配额取决于你的计费模式。

429 和 403 rateLimitExceeded / quotaExceeded 响应会在 error.errors[].reason 中包含可重试原因。请采用指数退避后重试;不要缩短轮询间隔。

错误处理

每个错误响应的格式都是 {"error": {"code": N, "message": "...", "errors": [{"reason": "..."}]}} ——在进行投影前检查 .error。reason 字符串是最有用的字段。

  • 401 — 凭据缺失或被拒绝。检查是否设置了 BQ_TOKEN(任意值均可)。如果问题仍然存在,说明此工作区尚未配置凭据——请报告此问题。
  • 403 accessDenied — 调用方没有项目或数据集的权限。检查 URL 中的项目(计费项目)与拥有数据的项目是否一致——它们可能不同。为数据授予 roles/bigquery.dataViewer,为计费项目授予 roles/bigquery.jobUser。
  • 404 notFound — 作业、数据集或表不存在,或者查询作业时遗漏了 location。仔细核对完整引用(project.dataset.table)。调用 jobs.get / getQueryResults 时始终传入 ?location=。
  • 400 invalidQuery — SQL 错误。message 中包含行号和列号。请记住设置 useLegacySql: false。
  • 作业的 status.errorResult — 查询已运行但失败。作业状态可以是 DONE,但仍然失败——获取结果前始终检查 status.errorResult。
  • 5xx / backendError — Google 端的暂时性错误。请采用退避策略重试。读取作业可安全重试;对于写入作业,请在重试前检查首次尝试是否已实际运行。

深入了解

references/api.md 中有更完整的端点目录——详细介绍作业配置对象(目标表、写入处置方式、加载/导出/复制作业)、数据集和表的创建/更新、例程以及行级访问策略。需要使用上文未涵盖的端点,或确认写入请求体的确切格式时,请阅读该文件。

评论

支持 Markdown