宁波市网站建设_网站建设公司_SSL证书_seo优化
2025/12/25 15:59:32 网站建设 项目流程

这个场景非常典型:报表页面用 URL 传参outId=7,8,SQL 写了o.id IN (${outId}),但预览只出来7的数据,没有8

下面我用“先复现 → 再解释原因 → 再给可落地方案”的方式,把它写成一篇完整教程。


1. 你的目标与现象

目标

在积木报表里让这类 SQL 支持多值查询:

...WHEREo.deleted=0ANDi.deleted=0ANDo.idIN(${outId})ORDERBYo.id,i.id

URL 传参类似:

/jmreport/view/xxx?token=...&tenantId=1&outId=7,8

现象

只查出了id=7的数据,id=8没出来。


2. 根因:${outId}在积木报表里常被当成“字符串”,导致 MySQL 只认到逗号前

积木报表 SQL 数据集的参数占位符常见写法是${参数名},并支持通过 URL 传参。([CSDN][1])

关键点在于:积木报表在解析参数时,经常把它当做“文本值”处理,最终 SQL 可能会变成类似这样(示意):

ANDo.idIN('7,8')

o.id是数字字段时,MySQL 会做隐式转换:
'7,8'转数字会被当成7(遇到逗号就截断),于是等价于:

ANDo.idIN(7)

所以你看到的结果就是:只有 7,没有 8


3. 为什么你写<foreach>会直接报错?

你写的这一段:

<foreach collection="outId"item="id"separator=",">#{id}</foreach>

这是MyBatis XML 动态 SQL语法,不是数据库 SQL 语法。

积木报表的SQL 数据集会把你输入的内容当成“纯 SQL 字符串”丢给数据库执行,数据库当然不认识<foreach>,于是报bad SQL grammar / SQLSyntaxErrorException这种语法错误(你日志里还出现了AND o.id IN AND o.id IN ( ),说明最终拼出来就是不合法 SQL)。


4. 你用FIND_IN_SET为什么能成功?

你最后改成:

ANDFIND_IN_SET(o.id,${outId})

它成功的本质原因是:

  • FIND_IN_SET(x, '7,8')这种写法,本来就是用来在“逗号分隔字符串列表”里找元素的;
  • 积木报表把${outId}当字符串后,很可能最终变成了:
FIND_IN_SET(o.id,'7,8')

于是o.id=7o.id=8都能匹配上。

这一招确实常被用作“积木报表 in 传参不生效”的 workaround(一些版本里更常见)。([CSDN][2])

⚠️ 但它也有明显缺点:基本用不上索引,数据量大时会慢(后面会说更推荐的写法)。


5. 推荐解法(强烈建议):用官方表达式函数DaoFormat.inNumber / DaoFormat.in

JimuReport 1.6.2+开始,官方文档明确提到:IN查询需要用函数来处理逗号分隔参数。([JimuReport][3])

5.1 数字 ID(比如 outId=7,8)✅推荐写法

ANDo.idIN(${DaoFormat.inNumber('${outId}')})
  • URL 继续传:outId=7,8
  • '${outId}'会得到字符串"7,8"
  • DaoFormat.inNumber(...)会把它转换成数值列表7, 8
  • 最终 SQL 变成真正的:
ANDo.idIN(7,8)

这才是**最标准、性能最好(可走索引)**的方式。

5.2 字符串类型(比如 code=AA,BB)

如果是字符串字段(需要带引号的那种),用DaoFormat.in(同一组函数体系)更合适,思路类似:把"AA,BB"变成('AA','BB')


6. 备选方案:继续用FIND_IN_SET(能用,但要知道代价)

如果你暂时不方便用DaoFormatFIND_IN_SET也能跑通,写法建议更稳一点(主动加引号,避免不同版本行为差异):

ANDFIND_IN_SET(o.id,'${outId}')

优点:简单粗暴,立刻可用。
缺点:大数据量时慢(通常不走索引)。([CSDN][2])


7. 另一个容易踩的坑:SQL 明明返回多行,但报表只显示 1 行?

如果你后面又遇到“SQL 在数据库执行有多行,但报表只渲染 1 行/空白行”的问题,多半是数据集类型填充方式配错了:

  • 数据集返回多行 → 你要按“集合”去渲染;
  • 积木报表里集合/对象在模板渲染上用法不同(常见提示:集合用#,对象用$,用错会出现空白行或只取第一条)。([JimuReport][4])

这个和你这次IN的问题是两条线,但经常一起出现。


8. 一套“遇到类似问题”的排查套路(新手可照抄)

  1. 先确认 URL 实际传进来了没
    在积木报表预览页看“参数面板/查询条件”是否能看到 outId 的值。

  2. 把参数替换后的 SQL 打出来看(最关键)
    你看到的LIMIT 1IN ('7,8')这类蛛丝马迹,就是定位问题的关键。

  3. 判断字段类型:数字还是字符串

  • 数字:优先DaoFormat.inNumber
  • 字符串:优先DaoFormat.in
  1. 实在不行再用FIND_IN_SET
    快速救火可以,但要考虑性能。

  2. 不要把 MyBatis 的<foreach>写进 SQL 数据集
    SQL 数据集不是 MyBatis XML。


9. 你这个报表的最终推荐 SQL(直接可用)

把你原 SQL 的这一段:

ANDo.idIN(${outId})

替换为(推荐):

ANDo.idIN(${DaoFormat.inNumber('${outId}')})

完整示例(仅展示 WHERE 相关):

WHEREo.deleted=0ANDi.deleted=0ANDo.idIN(${DaoFormat.inNumber('${outId}')})ORDERBYo.id,i.id

示例截图


需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询