用于在文件中创建数据库值的字符串格式化问题

时间:2013-04-13 12:41:44

标签: java regex string formatting string-formatting

我有一个bean类来维护用户数据:

soppose我已经创建了一个这样的postgresql数据库表:

StringBuffer sqlStr = new StringBuffer();
sqlStr.append("CREATE TABLE Users ("
        user_id         bigint,
        username        character varying NOT NULL,
        biography       character varying NOT NULL
);

&安培;我想创建一个查询命令并在其中注入我的String数据:

    sqlStr.append("INSERT INTO users(" +
            "user_id, username, biography)" +
            "\n\tVALUES (" + user.getID()+ "," + user.getUsername() + "," + user.getBiography()+");";

我的问题是,例如,如果来自我的方法的数据有引号或双引号或“,”我的命令将变得错误,假设用户传记是这样的:

  

你好,我是X先生的“IT专业人员”...

如果我运行我的应用程序并将输出保存在名为query.sql的文件中,我无法使用它,因为我的查询命令错误,因为引用&双引号,像这样:

INSERT INTO users(userid, username, biography)
     VALUES(2, 'Mehdi', 'hello, I'm Mr X an "IT Pro" ..');

我该如何解决这个问题?

2 个答案:

答案 0 :(得分:2)

您应该从不使用上述方法构建SQL查询。

“为什么不呢?”你问,好吧;从哪儿开始。典型的例子是Bobby Tables,更普遍的问题是SQL injection。这会使您的程序受到攻击,但也会随机失败 - 就像您描述的情况一样。

现在,解决方案。始终使用PreparedStatement构建查询。在你的例子中

final String query = "INSERT INTO users(user_id, username, biography) VALUES (?,?,?)";
final PreparedStatement ps = con.prepareStatement(query);
ps.setInt(1, user.getID());
ps.setString(2, user.getUsername());
ps.setString(3, user.getBiography());
ps.executeUpdate();

使用的更好的语法是SET语法而不是传统的VALUES语法。然后查询看起来像

final String query = "INSERT INTO users SET user_id = ?, username = ?, biography = ?";

修改

OP正在为脚本文件构建查询,而不是在代码中执行查询。

Apache Commons Lang中有一个实用程序类StringEscapeUtils。这有一个escapeSql方法。查看源代码,所有这一切都是使用另一个单引号转义单引号。

如果您使用单引号构建查询,则此方法有效:

VALUES (" + user.getID()+ ",'" + user.getUsername() + "'...

因此,一旦插入示例值,查询将来自:

VALUES (10 ,'hello, I'm Mr X an "IT Pro"'...

将成为

VALUES (10 ,'hello, I''m Mr X an "IT Pro"'...

“我是”中的撇号现在已经逃脱并且无害。

请注意,您显然需要转义值而不是查询,因此(假设您有一个static类的导入)

VALUES (" + user.getID()+ ",'" + escapeSql(user.getUsername()) + "'...

但是没有逃避其他sql字符,例如百分号。

在您提出更强大的解决方案时,这实际上是一种能够使代码工作的权宜之计。你应该提出一个更强大的解决方案。

答案 1 :(得分:0)

为什么不使用 PreparedStatement ?这也将为您提供更好的性能,因为SQL将在数据库端进行预编译。

您可以使用转义引号 String.replaceAll http://docs.oracle.com/javase/6/docs/api/java/lang/String.html#replaceAll(java.lang.String,java.lang.String)