You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

DB2 for i存储过程传入逗号分隔字符串在NOT IN子句失效问题

解决DB2 for i存储过程中NOT IN子句不生效的问题

我明白你现在遇到的困扰——明明传了逗号分隔的多个值,结果NOT IN根本没起到过滤作用,反而把整个字符串当成一个值存进了表字段里。这其实是因为你传递的参数格式和SQL解析逻辑不匹配导致的,咱们一步步来解决:

问题根源

你现在在Java里传的是'232/232','34fd/34//',这个字符串到了存储过程的code参数里,SQL会把它当成一个完整的字符串值。也就是说,你的NOT IN子句实际变成了:

table2.status not in ('\'232/232\',\'34fd/34//\'')

相当于你在找status等于这个超长字符串的记录,自然不会过滤掉任何单个的status值。

推荐解决方案(安全无注入风险)

方法1:使用STRTOK_TABLE表函数拆分字符串(DB2 for i 7.1及以上支持)

这个方法最简洁,利用DB2自带的表函数把逗号分隔的字符串拆分成独立的行,再用这些行作为NOT IN的条件。

首先修改存储过程的SQL逻辑:

create procedure history (in id varchar (3), in code varchar (2000))
begin
  insert into table1 
  select date_from, date_to, code 
  from table2 
  where table2.serial = id 
    and table2.status not in (
      -- 按逗号拆分code参数,取出每个独立的token
      select token from table(STRTOK_TABLE(code, ','))
    );
end

然后调整Java里的参数,去掉多余的单引号,只保留逗号分隔的原始值:

String codeString = "232/232,34fd/34//";

方法2:使用XMLTABLE拆分字符串(兼容更低版本DB2)

如果你的DB2版本不支持STRTOK_TABLE,可以用XMLTABLE来实现拆分:

create procedure history (in id varchar (3), in code varchar (2000))
begin
  insert into table1 
  select date_from, date_to, code 
  from table2 
  where table2.serial = id 
    and table2.status not in (
      -- 把逗号替换成XML格式的分隔符,再解析成行
      select trim(x.column_value) 
      from xmltable(('"' || replace(code, ',', '","') || '"')) as x
    );
end

Java端的参数同样需要改成不带单引号的逗号分隔字符串:

String codeString = "232/232,34fd/34//";

不推荐的方法(存在SQL注入风险)

如果你确定参数绝对安全(比如不是用户输入的内容),可以用动态SQL拼接语句,但这个方法有严重的注入风险,谨慎使用:

create procedure history (in id varchar (3), in code varchar (2000))
begin
  declare sql_stmt varchar(4000);
  -- 直接拼接code参数到SQL语句中
  set sql_stmt = 'insert into table1 select date_from, date_to, code from table2 where table2.serial= ? and table2.status not in (' || code || ')';
  prepare stmt from sql_stmt;
  execute stmt using id;
end

这种情况下Java端可以保留原来的带单引号的参数格式,但强烈不建议在生产环境使用。

内容的提问来源于stack exchange,提问作者bkashaf

火山引擎 最新活动