JDBC传递逗号分隔日期参数至Oracle PL/SQL IN查询报错如何解决
Oracle PL/SQL 实现多日期入参查询的解决方案
报错根因
你传入的I_dates是单个VARCHAR类型字符串,PL/SQL解析WHERE date IN (I_dates)时会将整个字符串识别为单个匹配值,而非多个日期值的列表。如果你传入的字符串自带单引号,Oracle会把字符串内的引号识别为语法标识符,就会抛出无效标识符的报错,和直接写死多值的SQL逻辑完全不同。
解决方案
方案1:拆分逗号分隔字符串转日期列表(最常用,无注入风险)
不需要在拼接入参时给每个日期加单引号,前端直接传入2019-05-01,2019-06-01格式的字符串即可,在PL/SQL中用正则拆分转成日期集合后匹配:
SELECT * FROM table1 WHERE date_col IN ( SELECT TO_DATE(TRIM(REGEXP_SUBSTR(I_dates, '[^,]+', 1, LEVEL)), 'YYYY-MM-DD') FROM DUAL CONNECT BY REGEXP_SUBSTR(I_dates, '[^,]+', 1, LEVEL) IS NOT NULL );
适配场景:不需要修改入参类型,改SQL逻辑即可快速上线。
方案2:动态SQL执行(灵活但需注意注入风险)
如果一定要用带单引号的入参格式,可以拼接为动态SQL执行:
DECLARE v_sql VARCHAR2(1000); BEGIN v_sql := 'SELECT * FROM table1 WHERE date_col IN (' || I_dates || ')'; -- 执行动态SQL,示例为打开游标 OPEN your_cursor FOR v_sql; END;
注意事项:必须提前校验I_dates的格式,仅允许日期和逗号、单引号存在,避免SQL注入风险。
方案3:集合类型入参(性能最优,安全性最高)
提前在Oracle中定义日期集合类型:
CREATE OR REPLACE TYPE date_list IS TABLE OF DATE; /
PL/SQL存储过程将入参定义为date_list类型,Java端通过JDBC的ARRAY类型直接传入日期数组,查询时直接匹配:
SELECT * FROM table1 WHERE date_col IN (SELECT column_value FROM TABLE(I_date_list));
适配场景:并发量高、查询性能要求高的系统,无SQL注入风险。
内容的提问来源于stack exchange,提问作者dsreddy
相关产品推荐
相关产品推荐

