将含单引号文本插入SQLite数据库报错,求解决方案
解决SQLite插入含单引号文本的语法错误问题
这个报错的原因很直观:你直接把带单引号的字符串拼进SQL语句里,破坏了SQL的语法结构。比如句子里的i'm会让SQL把'i'当成一个完整字符串,后面的m就成了无意义的语法碎片,自然触发syntax error。
解决这个问题的最佳实践是使用PreparedStatement,它不仅能自动处理单引号这类特殊字符,还能避免SQL注入风险,代码也更整洁。下面是修改后的完整代码:
重构后的数据库插入代码
try (Connection conn = DriverManager.getConnection(CONNECTION_STRING); PreparedStatement pstmt = conn.prepareStatement( "INSERT INTO " + TABLE_CONTACTS + " (" + COLUMN_LINE + ") VALUES (?)" )) { // 先删除旧表并创建新表 try (Statement statement = conn.createStatement()) { statement.execute("DROP TABLE IF EXISTS " + TABLE_CONTACTS); statement.execute("CREATE TABLE IF NOT EXISTS " + TABLE_CONTACTS + " ( " + COLUMN_LINE + " text )"); } // 批量插入数据(效率更高) for (String line : weFeelFine) { pstmt.setString(1, line); // 这里自动处理单引号等特殊字符 pstmt.addBatch(); } pstmt.executeBatch(); } catch (SQLException ex) { System.out.println("Something went wrong! " + ex.getMessage()); ex.printStackTrace(); }
为什么这个方案更靠谱?
- 自动转义特殊字符:
PreparedStatement会把你传入的字符串里的单引号自动转成SQL能识别的格式(比如把'变成''),完全不需要手动处理。 - 杜绝SQL注入:如果你的文本来自外部输入,直接拼接SQL会有被注入攻击的风险,而
PreparedStatement的参数化查询从根源上解决了这个问题。 - 代码更易维护:不用再拼接复杂的SQL字符串,参数设置逻辑清晰,后期修改也更方便。
(不推荐)临时应急方案
如果你暂时不想改成PreparedStatement,可以手动把字符串里的单引号替换成双单引号(SQL语法里用两个单引号表示字符串内的一个单引号):
private static void insertContacts(Statement statement, String lineNow) throws SQLException{ String escapedLine = lineNow.replace("'", "''"); statement.execute("INSERT INTO " + TABLE_CONTACTS + " (" + COLUMN_LINE + " ) VALUES('" + escapedLine + "')" ); }
但这个方法只解决了单引号的问题,遇到其他特殊字符(比如换行符、反斜杠)还是会出错,而且无法防范SQL注入,只适合临时救急,不建议长期使用。
内容的提问来源于stack exchange,提问作者Shlomi Shabtai
相关产品推荐
相关产品推荐

