不使用setString的Java SQL转义

不使用setString的Java SQL转义,java,sql,string,escaping,Java,Sql,String,Escaping,是否有一个内置的方法来转义SQL的字符串?我会使用setString,但碰巧我在同一个组合SQL语句中多次使用setString,我认为如果转义只发生一次,而不是每次都说setString,性能会更好。如果在变量中包含转义字符串,则可以重新使用它 在Java中没有办法做到这一点吗 当前方法,多源搜索。实际上,它们是三个完全不同的where语句,包括join,但在本例中,我将为每个表显示相同的where String q = '%' + request.getParameter("search")

是否有一个内置的方法来转义SQL的字符串?我会使用setString,但碰巧我在同一个组合SQL语句中多次使用setString,我认为如果转义只发生一次,而不是每次都说setString,性能会更好。如果在变量中包含转义字符串,则可以重新使用它

在Java中没有办法做到这一点吗

当前方法,多源搜索。实际上,它们是三个完全不同的where语句,包括join,但在本例中,我将为每个表显示相同的where

String q = '%' + request.getParameter("search") + '%';
PreparedStatement s = s("SELECT a,b,c FROM table1 where a = ? UNION select a,b,c from table2 where a = ? UNION select a,b,c FROM table3 where a = ?");
s.setString(1, q);
s.setString(2, q);
s.setString(3, q);
ResultSet r = s.executeQuery();
我知道这没什么大不了的,但我喜欢让事情更有效率,而且在某些情况下,使用+引号+而不是?然后在下面的某个地方可以找到setString。

如果将setString用于参数,例如PreparedStatement.setString,则可能不需要实际的转义-数据可能会以不需要转义的方式与SQL本身分开传递

您是否有任何具体迹象表明这确实是一个性能瓶颈?在数据库查询中,昂贵的部分似乎不太可能在本地设置参数…

如果对参数使用setString,例如PreparedStatement.setString,则可能不需要实际转义-数据可能会与SQL本身分开传递,以一种不需要逃跑的方式

您是否有任何具体迹象表明这确实是一个性能瓶颈?在数据库查询中,昂贵的部分似乎不太可能是在本地设置参数…

您可以从Apache commons使用:

org.apache.commons.lang.StringEscapeUtils.escapeSql(yourUnscapedSQL);
您可以从Apache commons使用:

org.apache.commons.lang.StringEscapeUtils.escapeSql(yourUnscapedSQL);

简单回答:我不会费心的。最好在最后时刻逃跑。当您尝试尽早转义一个字符串并将其保留时,验证所有字符串是否已准确转义一次变得更加困难。将字符串转义两次几乎和根本不转义一样糟糕!我见过很多程序试图提前转义字符串,然后遇到麻烦,因为他们需要更新字符串,然后程序员忘记重新转义,或者他们更新字符串的转义版本,或者他们有四个字符串,然后转义其中三个,我正在处理一个bug,一个程序员很早就对字符串进行了HTML转义,然后决定截断字符串以适应表单,最后试图输出一个以&am结尾的字符串。也就是说,他截断了他的逃逸序列,使其不再有效

转义字符串的CPU时间应该很短。除非您有大量的记录或非常大的字符串被重复使用,否则我怀疑节省下来的钱是否值得担心。您最好花时间优化查询:保存一条记录的读取可能比通过字符串转义逻辑消除1000次行程更有价值

回答:没有内置的功能。您可以很容易地编写一个:大多数风格的SQL只需要将任何单引号加倍。您可能还需要双反斜杠或一个或两个其他特殊字符。SQL引擎之间的差异是使用PreparedStatements并让JDBC担心它的一个重要理由。我个人认为应该有一个JDbC函数来进行转义,这样就可以知道DB引擎特定的任何需求。但事实并非如此


在任何情况下,都不清楚它将如何与准备好的声明一起工作。必须有某种方法告诉PreparedStatement不要转义这个字符串,因为它已经被转义了。在JDBC和DB引擎之间的对话中,谁真正知道表下发生了什么:也许它根本就不会真正逃避它,而是将它与查询分开传递。我想setString上可能有一个额外的参数,表示这个字符串是预先转义的,但这会增加复杂性和潜在的错误,只会获得很少的收益。

简短的回答:我不介意。最好在最后时刻逃跑。当您尝试尽早转义一个字符串并将其保留时,验证所有字符串是否已准确转义一次变得更加困难。将字符串转义两次几乎和根本不转义一样糟糕!我见过很多程序试图提前转义字符串,然后遇到麻烦,因为他们需要更新字符串,然后程序员忘记重新转义,或者他们更新字符串的转义版本,或者他们有四个字符串,然后转义其中三个,我正在处理一个bug,一个程序员很早就对字符串进行了HTML转义,然后决定截断字符串以适应表单,最后试图输出一个以&am结尾的字符串。也就是说,他缩短了他的逃跑顺序 它不再有效

转义字符串的CPU时间应该很短。除非您有大量的记录或非常大的字符串被重复使用,否则我怀疑节省下来的钱是否值得担心。您最好花时间优化查询:保存一条记录的读取可能比通过字符串转义逻辑消除1000次行程更有价值

回答:没有内置的功能。您可以很容易地编写一个:大多数风格的SQL只需要将任何单引号加倍。您可能还需要双反斜杠或一个或两个其他特殊字符。SQL引擎之间的差异是使用PreparedStatements并让JDBC担心它的一个重要理由。我个人认为应该有一个JDbC函数来进行转义,这样就可以知道DB引擎特定的任何需求。但事实并非如此

在任何情况下,都不清楚它将如何与准备好的声明一起工作。必须有某种方法告诉PreparedStatement不要转义这个字符串,因为它已经被转义了。在JDBC和DB引擎之间的对话中,谁真正知道表下发生了什么:也许它根本就不会真正逃避它,而是将它与查询分开传递。我想setString上可能有一个额外的参数,表示该字符串是预先转义的,但这会增加复杂性和潜在错误,但收获甚微。

不要使用org.apache.commons.lang.StringEscapeUtils.escapeSqlyourUnscapedSQL

它不会转义字符,如\

不要使用org.apache.commons.lang.StringEscapeUtils.escapeSqlyourUnscapedSQL



它不会转义\

您试图转义的字符是什么?向我们展示您的一些代码将对您有所帮助。@RMT:通过setString转义的所有字符我不希望由于搜索值而出现注入攻击或语法错误的可能性。您试图转义的字符是什么?这将对您有所帮助向我们展示您的一些代码。@RMT:setString转义的所有字符我不希望由于搜索的值而出现注入攻击或语法错误的可能性。这不太可能。这里没有瓶颈。我只是喜欢一个高效的代码,有时候它更可读。乔治:事实上,我不同意可读性,因为使用预先准备好的语句会使代码与数据分开。但我同意命名参数比位置参数更具可读性:这不太可能。这里没有瓶颈。我只是喜欢一个高效的代码,有时候它更可读。乔治:事实上,我不同意可读性,因为使用预先准备好的语句会使代码与数据分开。但我同意命名参数比位置参数更具可读性:为什么长答案似乎比短答案短:S+1表示描述良好answer@RMT当前位置因为我不能把事情放在一边,我不断返回并添加到我的简短答案中!为什么长答案看起来比短答案短:S+1表示描述良好answer@RMT当前位置因为我不能把事情放在一边,我不断返回并添加到我的简短答案中!作为对原始问题的评论,这会更好。它并没有真正回答这个问题,应该对其进行修改,以获得使用StringEscapeUtils.escapeSql的所有建议,imo将其命名为极其危险的StringEscapeUtils.escapeSql——正如Kim指出的,它并没有正确地转义sql。任何试图在生产中依赖StringEscapeUtils的人都将失败。这最好作为对原始问题的评论。它并没有真正回答这个问题,应该对其进行修改,以获得使用StringEscapeUtils.escapeSql的所有建议,imo将其命名为极其危险的StringEscapeUtils.escapeSql——正如Kim指出的,它并没有正确地转义sql。任何试图在生产过程中依赖电子产品的人都将失败。