Windmill 中编写 Microsoft SQL Server (MSSQL) 脚本:参数语法、S3Object 输入与结果流式导出
【免费下载链接】windmillOpen-source developer platform to power your entire infra and turn scripts into webhooks, workflows and UIs. Fastest workflow engine (13x vs Airflow). Open-source alternative to Retool and Temporal.项目地址: https://gitcode.com/GitHub_Trending/wi/windmill
Windmill 将 MSSQL 作为一等脚本语言支持,允许你直接在平台内编写 SQL Server 脚本,并复用其调度、触发器、变量与资源绑定等全套能力。本文基于 system_prompts/languages/mssql.md 展开,系统讲解 Windmill MSSQL 脚本的参数占位符约定、通过注释声明参数名与默认值的方法,以及两个与对象存储深度集成的实战场景:将 S3 文件作为脚本入参((s3object))消费,以及用-- s3指令把大结果集流式写入 S3。读完你就能在 Windmill 中写出可参数化、可处理文件、可避免大结果集内存缓冲的 MSSQL 脚本。
一、MSSQL 脚本在 Windmill 中的定位
Windmill 的脚本语言列表中对 MSSQL 有原生支持:在 backend/windmill-common/src/worker.rs 的 worker 可执行语言列表中注册了"mssql";在查询构建器 backend/windmill-common/src/query_builders.rs 中,ScriptLang::Mssql被映射到DbType::MsSqlServer,意味着 Windmill 内置的 SQL 查询构建(select/insert/update/delete/count 以及表元数据加载、外键与主键约束发现等)对 MSSQL 方言有专门的实现与测试覆盖。
这些语言级指导文档位于system_prompts/languages/,是前端 Copilot 与 CLI 生成代码时使用的单一事实来源(见 system_prompts/README.md)。也就是说,你按本文约定的语法书写 MSSQL 脚本,AI 辅助编写与 Windmill 运行时解析行为是一致的。
二、参数占位符:@P1、@P2与注释命名法
与 PostgreSQL 脚本用$1::{type}直接内联类型(对比 system_prompts/languages/postgresql.md)不同,MSSQL 脚本在 Windmill 中使用位置占位符:
- 参数引用采用
@P1、@P2、@P3…… 的形式; - 参数的真实名字、类型和默认值,通过写在语句之前的注释来声明。
基本示例:
-- @P1 name1 (varchar) -- @P2 name2 (int) = 0 SELECT * FROM users WHERE name = @P1 AND age > @P2;要点拆解:
| 注释片段 | 含义 | 说明 |
|---|---|---|
-- @P1 name1 | 将占位符@P1命名为参数name1 | 命名用于 Windmill UI 的输入表单与调用方传参 |
(varchar) | 参数类型 | 标注为 SQL Server 类型,用于输入校验与展示 |
(int) = 0 | 类型 + 默认值 | 默认值使该参数在脚本中变为可选 |
- 若省略默认值,则该参数在 UI 与 API 调用时为必填项。
- 占位符顺序与注释顺序一一对应,
@P1对应第一条注释,@P2对应第二条,以此类推。 - 实际 SQL 语句中的
@P1、@P2会被 Windmill 解析后替换为参数绑定,语句本身只写占位符,不要写成字面量。
这一约定同样适用于查询构建器场景:在 backend/windmill-common/src/query_builders.rs 中可以看到 MSSQL 与其他方言在 WHERE 子句处理上的差异(MSSQL 直接使用WHERE,不做AND替换),且mssql_eq_condition(同文件 query_builders.rs)专门处理了 MSSQL 的text、ntext、image等类型不能与=运算符直接比较的问题——这些内置构建逻辑同样以@P占位符体系为输入约定。
三、接收 S3Object 作为脚本参数
3.1 声明方式与运行时行为
当某个参数需要接收对象存储中的文件时,把参数类型声明为(s3object):
-- @P1 file (s3object)Windmill 会自动为该参数渲染一个S3 文件选择器(前端 UI 内可直接浏览并选择存储中的文件)。运行时,平台会替你完成下载与转换:
- 下载该文件;
- 将其绑定为
nvarchar(max)的 JSON 文本; - Parquet / CSV 文件:在服务端解码为一个 JSON 记录数组后传入;
- JSON / JSONL 文件:原样透传(pass through)。
这与 Windmill 内部对象存储/资产体系一致:在 backend/windmill-common/src/assets.rs 中可以看到脚本的S3Object输入与自动生成的 S3 picker 是资产图(asset graph)的一部分,AssetKind::S3Object会在依赖分析中生成从对象存储到脚本的边(同文件 assets.rs),从而支持基于资产的触发与依赖编排。
3.2 用 OPENJSON 消费
由于参数被绑定为 JSON 文本(nvarchar(max)),脚本内使用 SQL Server 内置的OPENJSON即可把它当作关系表查询:
-- @P1 file (s3object) SELECT id, name FROM OPENJSON(@P1) WITH (id INT, name NVARCHAR(200));OPENJSON把 JSON 文本解析为行集;WITH子句显式声明输出列及其类型(如id INT、name NVARCHAR(200)),未声明的字段会被忽略;- 对于 Parquet/CSV 输入,服务端已解码为 JSON 数组,因此
OPENJSON的用法完全一致; - 输出列类型请使用 SQL Server 类型(
INT、NVARCHAR(n)、BIGINT、DECIMAL(p,s)等)。
四、流式查询结果到 S3
4.1-- s3指令
当查询结果集很大时,把整份结果作为脚本返回值缓冲在内存中既不高效也可能超限。此时在脚本顶部加一条-- s3指令,即可让 Windmill 把结果集直接流式写入 S3:
-- s3 prefix=exports/users format=parquet SELECT id, name FROM users;- Windmill 负责将结果集流式写入对象存储文件;
- 脚本的最终返回值变为该文件的
S3Object引用(而非行数据本身); - 后续流程可以直接把这个
S3Object传给其他脚本、资源或触发下游任务。
4.2 可选键
-- s3指令后跟随key=value形式、以空格分隔的可选键,所有键都可省略:
| 键 | 含义 | 默认/取值 |
|---|---|---|
prefix | 对象键前缀(object key prefix) | 省略则由平台生成默认路径 |
storage | 命名存储(named storage) | 省略则使用工作区默认存储 |
format | 导出格式 | json(默认)、parquet、csv三选一 |
示例组合:
-- s3 prefix=analytics/daily format=csv SELECT created_at, event FROM events WHERE created_at >= DATEADD(day, -1, GETUTCDATE());-- s3 storage=exports format=parquet SELECT * FROM large_table;关于命名存储的寻址语义,可参考 backend/windmill-common/src/assets.rs 中 S3 引用的往返测试:s3://exports/x表示名为exports的命名存储,s3:///exports/x表示默认存储下的exports/x路径,显式存储桶则写作s3://mybucket/exports/x。理解这套 URI 约定有助于你判断prefix与storage组合出的对象键。
4.3 适用场景与注意点
- 适合:大批量查询导出、报表流水、需要把结果落盘供后续批处理/数仓消费的场景;
- 机制:行数据直接流式写入对象存储,而不是先缓冲为脚本返回值,显著降低内存压力;
- 行为差异:开启流式导出后脚本返回的是
S3Object而不是行集,下游消费方应按对象引用处理,而非按表格结果集处理; - 该指令与第三条的
(s3object)入参配合,可以轻松搭出"从 S3 读入 → SQL 处理 → 写回 S3"的完整文件型数据处理链路。
五、与姊妹语言的差异速览
Windmill 为每种 SQL 语言维护了独立的参数约定(见 system_prompts/languages/ 目录):
- MSSQL:
@P1、@P2占位符 + 注释声明-- @P1 name (type) = default;S3Object 绑定为nvarchar(max)JSON,用OPENJSON消费; - PostgreSQL:
$1::{type}内联类型转换;S3Object 绑定为jsonb,用jsonb_to_recordset消费(见 system_prompts/languages/postgresql.md); - 两者共享完全相同的
-- s3流式导出指令与可选键语义,跨数据库迁移脚本时仅需调整参数声明与 JSON 消费函数。
六、小结
Windmill 的 MSSQL 支持围绕三条核心约定展开:@P占位符 + 注释命名实现类型化参数与默认值;(s3object)类型把 S3 文件以 JSON 文本形式安全注入脚本并通过OPENJSON消费;-- s3指令将大结果集流式落盘并返回S3Object。这套约定同时服务于前端 Copilot、CLI 与运行时解析(由 system_prompts/ 目录统一维护、generate.py生成导出),并与 backend/windmill-common/src/query_builders.rs 中DbType::MsSqlServer的方言实现、backend/windmill-common/src/assets.rs 的资产依赖分析相互印证。按本文示例书写的脚本可直接在 Windmill 中运行、调试并接入调度与触发体系。
【免费下载链接】windmillOpen-source developer platform to power your entire infra and turn scripts into webhooks, workflows and UIs. Fastest workflow engine (13x vs Airflow). Open-source alternative to Retool and Temporal.项目地址: https://gitcode.com/GitHub_Trending/wi/windmill
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考