我的查询
attributes.replace(" ' ", "");
//also used SET "+attributes+"
String sql;
sql = "UPDATE diseaseinfo"
+ " SET ?=?"
+ "WHERE companyname = 'mycom' && diseaseName =?";
PreparedStatement preparedStmt = connects.prepareStatement(sql);
preparedStmt.setString(1, attributes);
preparedStmt.setString(2, attrData);
preparedStmt.setString(3, medname);
System.out.println(preparedStmt);
它给了我一个错误,因为查询在字符串中设置了列名,所以它在原因
上变成了这样 UPDATE diseaseinfo SET 'causes'='abc' WHERE companyname = 'mycom' and diseaseName ='fever'
通过这个问题,我知道我无法通过预先准备的声明添加动态列:https://stackoverflow.com/a/3136049/7794329
现在,真正的问题出现了:假设我将使用像这个问题中的简单更新查询:jdbc dymanic sql query with variable containg 's
它表示你不能在简单的sql查询中输入值,因为它会再次出现查询语法错误,例如:
SELECT * FROM diseaseinfo WHERE diseaseName = 'Adult Still's disease' AND name = 'add';
这里不会执行,因为''成人静止'
然后它不适用于简单查询。我现在应该怎么做?用什么?要设置动态列,请在查询中使用。
我不担心SQL注入,因为我正在本地工作。我只想让我的查询被执行。
答案 0 :(得分:4)
右。我们不能将标识符作为绑定参数提供。列的名称必须是SQL文本的一部分。
我们可以使用以下内容动态地将列的名称合并到SQL文本中:
sql = "UPDATE diseaseinfo"
+ " SET `" + colname + "` = ?"
+ " WHERE companyname = 'mycom' AND diseaseName = ?";
并为剩下的两个绑定参数提供值
preparedStmt.setString(1, attrData);
preparedStmt.setString(2, medname);
关于SQL注入你是完全正确的。
在SQL注入方面,作为绑定值提供,attrData
和medname
值中的单引号不会成为问题。
但是,如果我们没有保证colname
是“安全的”,那么通过将colname
变量合并到SQL文本中,我提供的示例是易受攻击的“包括在声明中。
因此,我们需要将值分配给colname
“安全”。
我们可以使用几种方法来做到这一点。最安全的是“白名单”方法。在colname
包含在SQL文本中之前,代码可以确保只将特定的“安全”值分配给colname
。
举个简单的例子:
String colname;
if (attributes.equals("someexpectedvalue") {
colname = "columnname_to_be_used";
} else if (attributes.equals("someothervalid") {
colname = "valid_columname";
} else {
// unexpected/unsupported attributes value so
// handle condition or throw an exception
}
更灵活的方法是确保colname
中不会出现反引号字符。在该示例中,colname
的值通过将其封装在反引号中而转义。因此,只要colname
中没有出现反引号字符,我们就会阻止将提供的值解释为除标识符之外的任何内容。
对于使用硬编码反引号字符的更通用(且复杂)的方法,我们可以考虑使用supportsQuotedIdentifiers
类的getIdentifierQuoteString
和java.sql.DatabaseMetaData
方法。
(在OP代码中,我们没有看到attributes
的内容的数据类型。我们看到一个名为replace
的方法的调用,以及提供给它的参数。假设attributes
是一个字符串,它应该是一个列名,我们不清楚为什么我们在字符串中有“空格单引号空间”,或者为什么我们需要删除它。除此之外,这个答案没有解决这个问题。)
答案 1 :(得分:0)
你问了一个有趣的问题..解决方案已经存在,因为YCF告诉你..如果你写
attributes.replace(" ' ", "");
然后空间也会计算
所以使用
attributes.replace("'", "");
使事情有效我也想添加
编写正确的字符串转义实用程序StringEscapeUtils.escapeSql(String)
(请注意,这是非常重要的,因为该方法已从更新版本的StringEscapeUtils中删除)。 -