我正在对带有 postgresql 数据库的 Web 应用程序的自制 QueryBuilder
类进行最后的润色。它对所有查询使用 PreparedStatement
并防止 SQL 注入(inject)。
但是我想要一种“快速而肮脏”的方式来表示 QueryBuilder
及其 toString()
方法,仅用于调试目的。该方法将按照通常传递到 PreparedStatement
的方式组装查询字符串,然后简单地将字符串中的每个 ?
替换为其相应的单引号值。 toString()
javadoc 将警告其他开发人员这是一个不安全的近似值,仅用于调试等。
我知道值应该将它们的单引号加倍(即 O'Connell
转义为 O''Connell
)。我忘记了还有其他特殊字符需要处理吗?我寻找了类似的问题,但只发现人们被责骂使用 PreparedStatement
(他们应该这样做,让记录显示)。
编辑: 不想使用第三方工具来完成这项特定任务,我真的只想在这里快速而肮脏。尽管如此,我还是很欣赏这些链接 - 我可能会考虑将它们用于其他用途。
最后编辑:感谢大家的帮助。我只想补充一点,对于那些从 google 偶然发现这里的人,不要对任何访问数据库的东西使用这些技巧,使用PreparedStatement
。
最佳答案
对于“快速而肮脏”的转义,将撇号加倍就足够了。但是,请注意字符串文字中已经存在的问号:
SELECT column FROM table WHERE column = 'A question?' or column = ?
您不想替换第一个问号。此外,应注意这些极端情况:
SELECT /* Is this a comment?? */ * FROM table
-- -- -- Another comment??
WHERE column = ?
该语句中只有一个绑定(bind)值。对于不太快捷的解决方案,您可以使用像 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
关于java - 快速而肮脏的 SQL 字符串转义,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7006586/