快速而又脏的SQL字符串转义
我正在为一个带有postgresql DB的Web应用程序的家庭滚动QueryBuilder
类进行最后润色。 它将PreparedStatement
用于所有查询,并受到SQL注入的保护。
但是,我想要一种“快速和脏”的方式来表示QueryBuilder
及其toString()
方法,仅用于调试目的。 该方法将组装查询字符串,通常传递给PreparedStatement
,然后简单地替换每个?
在字符串中具有相应的单引号值。 toString()
javadoc将警告其他开发人员,这是一个不安全的近似,仅用于调试等。
我知道这些值应该是他们的单引号加倍(即O'Connell
逃到O''Connell
)。 是否还有其他应该处理的特殊字符我忘记了? 我寻找类似的问题,但只发现人们被骂使用PreparedStatement
(他们应该,让记录显示)。
编辑:不打算使用第三方工具完成这个特定的任务,我真的只想在这里快速而肮脏。 我确实欣赏这些链接 – 我可能会将它们视为其他用途。
最后编辑:感谢所有有用的指示。 我只想补充一点,对于那些从谷歌这里绊倒的人来说,不要将这些技巧用于击中数据库的任何内容,请使用PreparedStatement
。
对于“快速和肮脏”的逃避,将撇号加倍是足够好的。 但是请注意字符串文字中已有的问号:
SELECT column FROM table WHERE column = 'A question?' or column = ?
您不想替换第一个问号。 此外,应该注意这些角落情况:
SELECT /* Is this a comment?? */ * FROM table -- -- -- Another comment?? WHERE column = ?
该语句中只有一个绑定值。 对于一个不那么快速和肮脏的解决方案,您可以使用像jOOQ这样的库来解决这个问题(免责声明:我为jOOQ背后的公司工作)。 它会为你做内联,也适用于更讨厌的数据类型:
DSLContext ctx = DSL.using(SQLDialect.POSTGRES); Object[] bindValues = { 1, "a'bc", Date.valueOf("2012-09-24"), "xy".getBytes() }; String string = ctx.query( "SELECT 1 WHERE A = ? AND B = ? AND C = ? AND D = ?", bindValues).toString();
以上将呈现
SELECT 1 WHERE A = 1 AND B = 'a''bc' AND C = date '2012-09-24' AND D = E'\\170\\171::bytea
如果你不反对使用第三方开源库,那么我想看看Apache Commons Lang的StringEscapeUtils.escapeSql(String str) 。
编辑:我刚检查了源代码 。 它只会像你一样用两个单引号( ''
)替换单引号( '
)。
也许你可以看一下Apache的StringEscapeUtils中的escapeJava(String input)
。
public static final String escapeJava(String input)
使用Java String规则转义String中的字符。