ToolJet 里的查询报错或者返回空,先不要改 SQL 结构,也不急着换数据源。打开运行面板看这一次执行的原始错误,再把问题落到两个位置上:参数有没有真的传进去、传进去的值和数据库字段类型对不对得上。这两处覆盖了日常遇到的大部分情况,而且都能通过页面行为、配置项和日志直接验证,不需要靠猜。
查询失败时,先在运行面板抄下完整错误原文,用它判断错误发生在参数绑定阶段、SQL 执行阶段还是结果映射阶段。提示里出现列名、表名、操作符,通常说明参数已经传到数据库层;出现参数数量、空值、未定义之类字眼,先查传参。分不清时,把动态参数换成一个写死的静态值跑一次,两次结果一比就知道问题在哪一层。不同数据源和驱动版本的报错文本不一样,以实际日志为准。
在运行面板读到完整错误信息并抄下原文
一次查询跑完,运行面板给出的线索通常有两类:执行状态(成功、失败、超时、仍在运行),以及数据源返回的原始内容。不同版本的入口位置和折叠方式略有差异,一般是点开查询编辑器下方的运行结果区,或者展开右侧面板里的响应与错误折叠箭头,就能看到完整文本。展开后不要只读第一行,把整段复制到编辑器里再看。
错误文本一般可以拆成三部分来读:
- 状态码或错误类别,例如连接被拒、权限不足、语法错误、类型错误、超时。
- 一句提示语,通常直接说明原因,例如找不到列、操作符不适用、参数个数不符。
- 涉及的具体对象,往往是字段名、表名、占位符序号或操作符。
如果提示里出现了具体的列名或表名,说明语句已经到达数据库层,参数绑定这一环大概率是通的;如果提示里是参数数量、未定义、空值这类字样,优先怀疑绑定阶段。抄写时建议连查询名、使用的数据源、报错时的参数值、错误堆栈首段一起记下来,后面做对照时这几项能帮你区分两次运行。
确认查询参数在组件里已被赋值
参数为空和参数值错误,在运行面板里的表现并不一样,但都很容易被当成「查询没数据」。
- 参数为空:绑定的表达式没取到值,常见原因是组件名写错、组件尚未渲染、字段名不对。条件恒不成立,查询往往不报错,只是返回空结果。
- 参数值错误:值确实传进去了,但和你以为的不是同一个,例如下拉框传的是显示文本而不是值,多选组件传的是数组而不是单个值,表达式返回的是字符串而字段是数字。
参数面板里常见的两种写法如下,放在查询编辑器的参数区使用:
-- 写法一:在 SQL 里直接绑定 select id, status, created_at from orders where status = {{components.statusSelect.value}} and customer_id = {{components.customerInput.value}} -- 写法二:SQL 用占位符,参数在参数面板定义 select id, status from orders where status = $1 and customer_id = $2 -- 参数面板: -- status -> {{components.statusSelect.value}} -- customer_id -> {{components.customerInput.value}}两种写法都可以,关键是参数面板里的值有没有被求值。判断办法是临时建一个只返回参数本身的查询,例如select {{components.statusSelect.value}} as probe,运行后看运行面板返回什么;也可以把参数值显示在一个文本组件上。看到未定义、空字符串、数组形式的值,问题就在传参这一层,不必再改 SQL。
核对传入值与数据库字段类型是否匹配
参数确实传进去了,报错依旧存在,就往类型上查。常见的类型不匹配现象有这些:
- 数值列和字符串参数比较,或字符串列和数字参数比较,数据库无法直接比较,通常提示操作符或类型不适用。
- 日期、时间列收到字符串,格式或时区对不上,可能报转换失败,也可能不报错但一行都匹配不到。
- 布尔列收到文本形式的真假值,或者收到数字 0 和 1。
- 状态、枚举列收到大小写不一致的值,例如传入 Active,库里存的是 active。
- 把数组传给单值占位符,或者把单个值传给需要列表的位置。
修正方向一般是三选一:在 SQL 里显式转换,把参数转成数值或日期类型再比较;在参数面板里转换,把组件值转成目标类型后再绑定;或者回到查询设计,让占位符类型和列类型对齐。具体驱动会报什么错、错误文本长什么样,不同数据源和版本并不一致,需要以运行面板里的实际日志为准,不要拿别人的错误码直接对号入座。
用静态值替换动态参数做一次对照
这一节的目的是把问题锁死在「动态传参路径」上。操作步骤如下:
- 先复制一份原查询,保留一份可回退的版本,不要直接改原查询。
- 在副本里把绑定表达式替换成一个明确的静态值,值要和「动态值本应等于的结果」完全一致,包括引号、大小写、日期格式和时区。
- 用同样的入口触发运行,比较两次结果:错误文本是否相同、返回行数是否一致、关键字段的值是否一致。
- 把差异点记下来,再决定回到第 2 节查传参,还是留在本节继续查 SQL 和字段。
结果对照的判断方式:静态值正常、动态值报错,问题在传参路径,重点看组件名、取值方式、参数面板绑定,以及组件在运行时是否已经渲染;静态值也报错,问题在语句本身或字段类型;两次都不报错但结果不同,说明实际传进去的值和你以为的不一样,回到参数实际值那里确认。
把修正后的查询保存并在预览页复核
改完查询先保存,再切到应用的预览模式,用接近真实用户的路径复现一次:先在下拉框里选择,再在输入框里填值,然后点触发查询的按钮,观察页面上的变化。
预览页需要重点看的几项:
- 表格或列表组件有没有数据,行数是否合理,空值是整列为空还是个别字段为空。
- 数值、日期字段的显示是否正常,有没有出现类似非法日期的占位文本。
- 触发按钮的状态,是否一直停在加载中、是否被禁用、点击后是否重复触发查询。
- 运行面板在预览模式下是否还输出错误。
- 组件的默认值,在用户还没有手动选择之前参数是什么,页面加载时是否已经跑过一次查询并失败。
如果编辑器里调试通过、预览页仍然报错,多半是预览环境下的组件状态、默认值或数据源权限与编辑器不同。这时先用同样的静态值再对照一次,确认是传参差异还是权限差异,确认无误后再保存应用版本。整个排查顺序不变:先读原始错误,再查参数赋值,然后核对字段类型,最后用静态值对照并在预览页复核。