PreparedStatement setString IN 传多个参数

在使用PreparedStatement处理IN操作时,直接传入以逗号分隔的字符串会导致查询错误。预编译的SQL不接受字符串如'a,b,c',而是将其视为一个整体。解决方法是手动替换逗号并添加单引号,或者根据分隔符创建对应数量的占位符,并将字符串切割成多个参数进行传入。对于PG数据库,此问题尤其需要注意。" 112223727,10545308,延时摄影技巧:用C语言计算日出日落时间,"['C语言编程', '摄影技巧', '延时摄影', '设备推荐', '日出日落摄影']

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

今天在使用PreparedStatement进行预编译时,发现使用IN(String) 传入一个字符串一逗号为分隔符却失效,例如传入"a,b,c", 查询的不是"a" "b" "c"三个数据,而是"a,b,c"一个数据

 

SELECT d.* FROM TLK_列表_分页 d WHERE 1=1  AND ITEM_多行文本二 IN ( ?)

这条语句中的参数在使用PrepareStatement来预编译之后,是不可以传入一个拼接字符串的,比如

String test="'a','b','c'";
prepareStatement.setString(1,test);

想要达到执行效果

SELECT d.* FROM TLK_列表_分页 d WHERE 1=1  AND ITEM_多行文本二 IN ('a','b','c')

但是实际执行的sql语句是:

SELECT d.* FROM TLK_列表_分页 d WHERE 1=1  AND ITEM_多行文本二 IN ('a'',''b'',''c')

 

它不是查询 'a','b','c'这三个元素,而是查询'a,b,c,'这一个元素,所以达不到预期的效果

后来想过既然它插入的字符串是逗号两边少了单引号的话我就replace把 ","换成" ',' "

这样以后实际执行的sql语句是:

SELECT d.* FROM TLK_列表_分页 d WHERE 1=1  AND ITEM_多行文本二 IN ('a'',''b'',''c')

单引号变成了双引号,其实是sql防注入起了作用,它对单引号自动进行了转义 ' 变成了  '' 给单引号加多一个引号进行了转义。

于是只好使用笨办法,

String test里面有几个参数,那就有几个占位符 ?

就是当 String test="'a','b','c'"; 有两个逗号时,sql就应该是:

SELECT d.* FROM TLK_列表_分页 d WHERE 1=1  AND ITEM_多行文本二 IN ( ?,?,?)

这样就OK了。

添加占位符的代码如下:

        
                String temp = "IN ( ? ";
          //判断逗号出现的次数
int n = test.length() - test.replaceAll(",", "").length(); //根据参数的数量决定占位符的数量 if (sql.contains(temp)) {
            //循环添加占位符的次数要比逗号出现的次数多一次,即参数的数量。
for (int i = 0; i < n; i++) { sql = sql.replace(temp, temp + ",?"); temp = temp + ",?"; } } }

 这样为sql添加了对应的占位符后,如果不把test字符串进行切割,依然会报错,因为如果进行了添加占位符,你的sql变成了

SELECT d.* FROM TLK_列表_分页 d WHERE 1=1  AND ITEM_多行文本二 IN ( ?,?,?)

这样你就需要传入三个参数,仅仅是传入“a,b,c”的话是满足不了条件的。

     List<Object> sqlParameters;

 if (text.contains(",")) {
                int n = text.length() - text.replaceAll(",", "").length();
                //切割参数添加到sqlParameters
                for (int i = 0; i <= n; i++) {
                    String s = text.split(",")[i];
                    sqlParameters.add(i, text.split(",")[i]);
                }
                //添加完切割的参数后删除原来未切割的参数
                sqlParameters.remove(text);
            }

用List切割完以后就可以传入数据了。

 for (Object sqlParameter : sqlParameters) {
                parameterIndex++;
                if (sqlParameter instanceof String) {
                    preparedStatement.setString(parameterIndex, (String) sqlParameter);
                }

这个写法是可以满足PG数据库的

可以参考网站:https://blog.youkuaiyun.com/lismooth/article/details/76934980

转载于:https://www.cnblogs.com/a565810497/p/10827154.html

public static void getconnect(String webName,String detailUrl,String title,String detailResult,String date,String currDate) throws Exception { // DriverManager 注册驱动 // Connection 数据库连接对象 url(指定连接的路径 语法:“jdbc:mysql://ip地址:端口号/数据库名称”) Class.forName("oracle.jdbc.driver.OracleDriver"); Connection com = DriverManager.getConnection("jdbc:oracle:thin:@192.168.2.42:1521:orcl", "bxkc", "bxkc"); System.out.println("successfully"); try { // 创建预编译的SQL插入语句 String sql = "inset into XIN_XI_INFO_TEST(SOURCE_NAME,DETAIL_LINK,DETAIL_TITLE,DETAIL_CONTENT,PAGE_TIME," + "CREATE_TIME,LIST_TITLE,CREATE_BY)" + "value (?,?,?,?,?,?,?)"; PreparedStatement preparedStatement = com.prepareStatement(sql); // 设置参数的值 preparedStatement.setString(1, webName);//网站名 preparedStatement.setString(2, detailUrl);//详情链接 preparedStatement.setString(3, title);//详情标题 preparedStatement.setString(4, detailResult);//正文HTML preparedStatement.setString(5, date);//列表时间 preparedStatement.setString(6, currDate);//创建时间 preparedStatement.setString(7, title);//列表标题 preparedStatement.setString(8, "zzh");//创建者名称 // 执行预编译的语句 int rowsAffected = preparedStatement.executeUpdate(); if (rowsAffected > 0) { System.out.println("Insertion successful. Rows affected: " + rowsAffected); } else { System.out.println("Insertion failed."); } // 关闭PreparedStatement preparedStatement.close(); } catch (SQLException e) { e.printStackTrace(); } // 执行 增删改查 (DML)语句用 int executeUpdate(Sting sql); // 执行 DQL 语句 ResultSet executeQuery(String sql); // 对象释放 void close(); com.close(); }无效的列索引这是什么意思
最新发布
03-08
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值