zplCloud Blog
SQL Server 作为数据源:消除导出循环
连接字符串从不离开你的机器。筛选、排序和分页以参数化 T-SQL 在你的服务器上运行。
导出循环,以及它为何会坏
标签数据存在于 ERP、WMS 或 Azure SQL 数据库中。惯常做法是导出 CSV、修正列名、上传、打印——然后明天重复,因为 CSV 已经过时。
zplCloud data hub 消除了导出。你网络内的 CLI agent 持有 SQL Server 连接字符串,平台向它发送查询描述,只有结果行返回。数据库从不暴露到互联网,凭证从不存储在云中。
这篇文章讲的是精确机制:什么在哪里运行、生成什么 SQL、硬性限制是什么。
架构,一段话
zplcloud proxy 打开一条到 api.zplcloud.com 的出站 TLS 连接(SignalR)。没有入站端口、没有 NAT 规则、没有 VPN。当你在平台中打开数据源时,后端向 agent 发送一个请求对象 - 基础查询、过滤、排序、偏移、限制 - agent 将其转换为 T-SQL,用你的数据库用户对你的 SQL Server 执行,并返回行。连接字符串只存在于 agent 进程内存及其本地配置中。
第 1 步 - 用一个或多个服务器启动 agent
# 允许多个 --sql 标志;NAME 是你在平台中选择的名称。
zplcloud proxy --agent "Lager" \
--sql PROD="Server=127.0.0.1;Database=erp;User Id=zplcloud;Password=…;Encrypt=True;TrustServerCertificate=True" \
--sql WAREHOUSE="Server=sql-wh.internal.lan,1433;Database=logistik;User Id=zplcloud;Password=…;Encrypt=True;TrustServerCertificate=True"
等价方式,不把秘密放进命令行(它们会进 shell 历史):
# Windows PowerShell - 每个服务器一个变量,名称在中间
$env:ZPLCLOUD_SQL_PROD_CONNECTION = "Server=127.0.0.1;Database=erp;User Id=zplcloud;Password=…;Encrypt=True;TrustServerCertificate=True"
zplcloud proxy --agent "Lager"
启动横幅列出发现的内容:SQL servers: PROD, WAREHOUSE。对平台的认证用 --api-key <key> 或 ZPLCLOUD_API_KEY。
为无人值守操作做持久化:
- Windows:
setx ZPLCLOUD_SQL_PROD_CONNECTION "…",或zplcloud proxy --agent "Lager" --service-install --api-key sk_zplcloud_… - Linux/Raspberry Pi: 同样的
--service-install标志;它会写入 systemd 单元zplcloud-agent.service,带Restart=always - 用文件替代 env: 二进制旁的
sqlservers.json或~/.zplcloud/,形如{ "sqlServers": { "PROD": "Server=…" } } - Docker:
docker-compose.agent.yml中的ZPLCLOUD_SQL_PROD_CONNECTION
让人浪费一小时连接字符串注意事项
Encrypt=True;TrustServerCertificate=True是自签名证书内部服务器的务实搭配。有了真证书后去掉TrustServerCertificate。- 命名实例需要
Server=host\INSTANCE;非默认端口是Server=host,1433- 逗号,不是冒号。 - 使用专用 SQL 登录,仅对标签所需的那几张表授予
SELECT。agent 以该用户执行所有操作,所以数据库是权限边界——不是平台。
第 2 步 - 创建数据源
在数据源中,运行中的 agent 出现在 Remote SQL Server 下,每个配置名一个芯片。点击芯片预填表单。
| 字段 | 值 |
|---|---|
| 名称 | Lager-Artikel |
| 类型 | SQL Server |
| 服务器 | PROD(--sql PROD=… 中的名称) |
| 查询 | SELECT ean, name, price FROM artikel |
测试运行 SELECT 1 并返回 server · database。字段通过带 CommandBehavior.SchemaOnly 的 SELECT TOP 1 * 读取列元数据 - 它获取模式而不拉取数据。如果深度嵌套的查询不返回模式,agent 会用 SingleRow 重试一次。
第 3 步 - agent 实际执行什么
你的基础查询被包装为子查询。过滤、排序和分页由 agent 附加:
SELECT * FROM ( SELECT ean, name, price FROM artikel ) AS ds
WHERE ean LIKE @p0
ORDER BY name
OFFSET 0 ROWS FETCH NEXT 10 ROWS ONLY
有三件事值得读两遍:
1. 值是参数,绝不是字符串拼接。 过滤器构建器发出 @p0、@p1、…,并通过 SqlCommand.Parameters 绑定值。用户输入的值在任何地方都不会变成 SQL 文本。
2. 分页是原生的。 limit 10 变成 FETCH NEXT 10 ROWS ONLY;SQL Server 完成工作,只在线路上返回十行,而不是一百万。
3. 行数是独立查询。 当你要求总数时,agent 用相同的 WHERE 和相同参数执行 SELECT COUNT(*) FROM (<base>) AS ds。
硬性限制(来自 agent 源码)
| 限制 | 值 | 适用处 |
|---|---|---|
| 每次请求行数 | 1000(RowCap) | limit 被钳制到 1…1000;未设置时默认 100 |
| 命令超时 | 15 s | 测试、describe、查询和计数 |
| 语句类型 | 仅 SELECT | 基础查询被验证;多语句被拒绝 |
| 排序/过滤列 | 已验证标识符 | 不作为自由格式 SQL 透传 |
如果你在一个视图中需要超过 1000 行 - 批量打印、完整目录 - 平台用递增的 OFFSET 翻页遍历结果集。每页是对你服务器的一次独立 1000 行请求,所以无论总量多少内存都保持平稳。
15 秒超时是刻意的。如果你的基础查询无法在 15 秒内应答,它属于索引视图或带正确索引的表,而不是标签数据源。
第 4 步 - 在设计器和 Print Views 中使用
- 设计器 → 测试数据 选项卡 → 数据源: 选择数据源并按加载。字段 binding 用真实行而不是占位文本渲染,所以你在任何东西到达打印机前就能看到实际字段长度。
- Print Views → 配置 → 数据源(Data Hub): 视图的预览及其打印使用实时查询。操作员看到的是当前数据;没有人重新上传 CSV。
故障模式及含义
| 症状 | 原因 |
|---|---|
| agent 启动但没有芯片出现 | --sql 名称缺失,或 agent 用另一个 workspace 的密钥认证 |
测试 立即失败 | 连接字符串错误(实例、端口、凭证) - 错误从 SQL Server 透传 |
测试 挂起后失败 | 15 s 超时:从 agent 机器服务器不可达,或防火墙静默丢弃包 |
字段 无返回 | 基础查询对 SchemaOnly 嵌套太深;agent 回退到 SingleRow,这至少需要一行存在 |
| 查询可用,Print View 为空 | 视图绑定到另一个数据源,或过滤器排除了所有行 |
套餐
data hub(通过 CLI agent 的 SQL Server 和 MongoDB 数据源)属于 Pro 套餐。详情见定价页面。