mcpField
Q
query

query

github.com/duckdb数据与数据库6131.5k 次安装28 周前更新
代码仓库

关于 query

使用 DuckDB 查询文件或已保存会话数据的 skill。它可将自然语言请求转为 SQL、执行前估算结果规模、运行查询并解读结果。

主要功能

  1. 01判断会话模式或临时模式
  2. 02将自然语言转换为 SQL
  3. 03执行前估算结果规模
  4. 04沙箱化执行文件查询
  5. 05解读结果并处理错误

适用场景

  1. 01查询 CSV 或 Parquet 文件
  2. 02检查已保存会话中的表
  3. 03用自然语言问题获取 SQL 查询结果

安装

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

$npx skills add https://github.com/duckdb/duckdb-skills --skill query

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

详细介绍

你正在帮助用户使用 DuckDB 查询数据。

输入:$@

请按顺序执行以下步骤。

步骤 1 — 解析状态并确定模式

在以下任一位置查找现有状态文件:

STATE_DIR=""
test -f .duckdb-skills/state.sql && STATE_DIR=".duckdb-skills"
PROJECT_ROOT="$(git rev-parse --show-toplevel 2>/dev/null || echo "$PWD")"
PROJECT_ID="$(echo "$PROJECT_ROOT" | tr '/' '-')"
test -f "$HOME/.duckdb-skills/$PROJECT_ID/state.sql" && STATE_DIR="$HOME/.duckdb-skills/$PROJECT_ID"

如果找到,请确认它引用的数据库仍可访问:

duckdb -init "$STATE_DIR/state.sql" -c "SHOW DATABASES;"

现在确定模式:

  • 临时查询模式:存在 --file 标志,或 SQL 引用了文件路径/字面值(例如 FROM 'data.csv'),或 STATE_DIR 为空。
  • 会话模式:已设置 STATE_DIR,且输入引用了表名、使用自然语言,或是未引用文件的 SQL。

如果不存在状态文件,且未引用文件,则回退到针对 :memory: 的临时查询模式——用户必须在 SQL 中直接引用文件。

如果状态文件存在,但其中任意 ATTACH 失败,则提醒用户并回退到临时查询模式。

步骤 2 — 检查是否已安装 DuckDB

command -v duckdb

如果未找到,则委托给 /duckdb-skills:install-duckdb,然后继续。

步骤 3 — 按需生成 SQL

如果输入是自然语言(而非有效 SQL),请使用下方的 Friendly SQL 参考生成 SQL。

在会话模式下,先获取架构信息,以便生成查询:

duckdb -init "$STATE_DIR/state.sql" -csv -c "
SELECT table_name FROM duckdb_tables() ORDER BY table_name;
"

然后针对相关表:

duckdb -init "$STATE_DIR/state.sql" -csv -c "DESCRIBE <table_name>;"

使用架构上下文和 Friendly SQL 参考生成最合适的查询。

步骤 4 — 估算结果大小

执行前,估算查询是否可能产生非常大的结果,从而在返回到此对话时消耗过多令牌。

会话模式 — 检查相关表的行数:

duckdb -init "$STATE_DIR/state.sql" -csv -c "
SELECT table_name, estimated_size, column_count
FROM duckdb_tables()
WHERE table_name IN ('<table1>', '<table2>');
"

临时查询模式 — 探查数据源:

duckdb :memory: -csv -c "
SET allowed_paths=['FILE_PATH'];
SET enable_external_access=false;
SET allow_persistent_secrets=false;
SET lock_configuration=true;
SELECT count() AS row_count FROM 'FILE_PATH';
"

评估:

  • 如果查询已有 LIMIT、count() 或其他可限制输出的聚合操作 -> 安全,可以继续。
  • 如果数据源有超过 1M 行,且查询没有 LIMIT 或聚合操作 -> 告知用户: “此查询会返回非常庞大的结果集。在此处显示会消耗大量令牌并增加成本。建议添加 LIMIT 1000 或聚合操作,以控制输出规模。” 运行原查询前请征求用户确认。
  • 如果数据大小超过 10 GB -> 还需提醒: “此表超过 10 GB,查询可能需要一些时间才能完成。” 用户确认后继续。

对于结果范围天然受限的查询(例如 DESCRIBE、SUMMARIZE、聚合操作、count()),跳过此步骤。

步骤 5 — 执行查询

临时查询模式(在沙盒中运行——仅可访问被引用的文件):

duckdb :memory: -csv <<'SQL'
SET allowed_paths=['FILE_PATH'];
SET enable_external_access=false;
SET allow_persistent_secrets=false;
SET lock_configuration=true;
<QUERY>;
SQL

将 FILE_PATH 替换为从查询或 --file 参数中提取的实际文件路径。 如果引用了多个文件,请将所有路径都包含在 allowed_paths 列表中。

会话模式(用户信任的数据库):

duckdb -init "$STATE_DIR/state.sql" -csv -c "<QUERY>"

对于多行查询,使用带 -init 的 heredoc:

duckdb -init "$STATE_DIR/state.sql" -csv <<'SQL'
<QUERY>;
SQL

多行查询始终使用 heredoc(<<'SQL'),以避免 shell 引号问题。

步骤 6 — 处理错误

  • 语法错误:显示错误,建议修正后的查询,然后重新运行。
  • 缺少扩展(例如 Extension "X" not loaded):委托给 /duckdb-skills:install-duckdb <ext>,然后重试。
  • 未找到表(会话模式):使用 FROM duckdb_tables() 列出可用表,并建议修正名称。
  • 未找到文件(临时查询模式):使用 find "$PWD" -name "<filename>" 2>/dev/null 定位文件,并建议修正后的路径。
  • 持续出现或含义不明的 DuckDB 错误:使用 /duckdb-skills:duckdb-docs <error message or relevant keywords> 搜索文档获取指导,然后应用修复并重试。

步骤 7 — 展示结果

向用户展示查询输出。如果结果超过 100 行,请说明结果已截断,并建议在查询中添加 LIMIT。

对于自然语言问题,还需简要解读结果。


DuckDB Friendly SQL 参考

生成 SQL 时,优先使用以下符合 DuckDB 惯例的构造:

紧凑子句
  • FROM 优先:FROM table WHERE x > 10(隐式使用 SELECT *)
  • GROUP BY ALL:自动按所有非聚合列分组
  • ORDER BY ALL:按所有列排序,以确保结果确定
  • SELECT * EXCLUDE (col1, col2):从通配符中排除列
  • SELECT * REPLACE (expr AS col):就地转换列
  • UNION ALL BY NAME:合并列顺序不同的表
  • 百分比 LIMIT:LIMIT 10% 返回一定百分比的行
  • 前缀别名:使用 SELECT x: 42,而非 SELECT 42 AS x
  • SELECT 列表允许尾随逗号
查询功能
  • count():无需使用 count(*)
  • 可复用别名:在 WHERE / GROUP BY / HAVING 中使用列别名
  • 横向列别名:SELECT i+1 AS j, j+2 AS k
  • COLUMNS(*):对多列应用表达式;支持正则表达式、EXCLUDE、REPLACE 和 lambda
  • FILTER 子句:使用 count() FILTER (WHERE x > 10) 进行条件聚合
  • GROUPING SETS / CUBE / ROLLUP:高级多级聚合
  • 每组 Top-N:max(col, 3) 以列表形式返回前 3 项;也可使用 arg_max(arg, val, n)、min_by(arg, val, n)
  • DESCRIBE table_name:架构摘要(列名和类型)
  • SUMMARIZE table_name:即时生成统计概览
  • PIVOT / UNPIVOT:在宽格式和长格式之间重塑数据
  • SET VARIABLE x = expr:定义 SQL 级变量,并使用 getvariable('x') 引用
数据导入
  • 直接查询文件:FROM 'file.csv'、FROM 'data.parquet'
  • 通配符匹配:FROM 'data/part-*.parquet' 可读取多个文件
  • 自动检测:自动推断 CSV 标头和架构
表达式和类型
  • 点运算符链式调用:'hello'.upper() 或 col.trim().lower()
  • 列表推导式:[x*2 FOR x IN list_col]
  • 列表/字符串切片:col[1:3]、负索引 col[-1]
  • STRUCT. 表示法*:SELECT s.* FROM (SELECT {'a': 1, 'b': 2} AS s)
  • 方括号列表:[1, 2, 3]
  • format():使用 format('{}->{}', a, b) 格式化字符串
连接
  • ASOF 连接:对有序数据(例如时间戳)进行近似匹配
  • POSITIONAL 连接:按位置而非键匹配行
  • LATERAL 连接:在子查询中引用之前的表表达式
数据修改
  • CREATE OR REPLACE TABLE:无需先执行 DROP TABLE IF EXISTS
  • CREATE TABLE ... AS SELECT (CTAS):根据查询结果创建表
  • INSERT INTO ... BY NAME:按列名而非位置匹配列
  • INSERT OR IGNORE INTO / INSERT OR REPLACE INTO:实现 upsert 模式

评论

支持 Markdown