此贴讲该错误和网上的大部分不同,此错误是在特定的技术栈框架下触发的。这里的SQL通过ibatis编写时并不会报错,而仅仅是在mybatis框架下编写才会产生报错。
背景
- 1、mybatis采用注解使用merge into对多条数据进行操作:
- 2、由于需要过滤一下U表,增加过滤条件:
- 3、这个时候就报错了:
- 4、此刻很明显的可以定位产生此错误的原因,就是传入参数对U表进行过滤的语句;
- 5、使用自定义的provider类构造SQL语句返回执行:
并不会报错,接着手动将数据编入SQL通过oracle客户端执行,执行成功,由此可以判断想要执行的SQL语法上是没有问题的。
解决
- 1、判断是不是此处不可以使用子查询,修改SQL,不传入参数:
执行该查询,发现并不会报错,由此可以推断,此处并不是子查询的问题,而是通过mybatis框架传参导致的问题; - 2、判断是不是由于预编译的原因而导致的问题,使用$符合拼接的方式来创建SQL:
执行报错:
很明显,缺少引号所致,修改SQL,添加引号:
执行成功:
由此可以发现拼接时需要拼上引号才能实现,推断预编译时是否也缺少引号; - 3、使用#传参时也加上引号:
报错,由此可以发现参数列与实际接收的参数都不一样了,所以不能通过加引号的方式去解决,查找资料,有人说是oracle的bug,有人说将数据库表的CURSOR_SHARING = force注释掉就行了,还有人说与绑定变量有关等等一系列的说法,但通过上述的分析与测验,只能归结于mybatis在预编译的时候产生的问题,毕竟在我用mybatis的前身ibatis时并不会产生此问题,一时半会也无新的解决思路,上述也提到了两种解决方案:
- 采用自定义provider类构造SQL语句返回执行;
- 采用引号+$符号拼接的方式将数据传入SQL执行;
这两种方案都是可行的,至于使用预编译为何无法执行的问题只能待以后有新的思路再来解决了。