查询参数只能取代文字值 – 即通常放置引用的字符串文字,引用的日期文字或数字文字.因此,字符串值将始终被解释为字符串文字,就像您使用单引号将其放入查询中一样.
对于列名,表名,SQL表达式,SQL关键字等,必须在调用prepare()之前将这些值插入到SQL查询中.
为了最安全,请使用白名单,以便用户输入永远不会逐字插入到SQL查询中.在查询中使用之前,始终验证用户输入(或任何其他内容).
你的评论:
我不确定你到底在做什么.听起来你要么想要t.targetLang等于文字数字,要么是固定字符串’targetLang’.如果是这样,我不知道你为什么要做一个子查询 – 你应该只使用一个查询参数:
where i.userID = ? And i.translated = 0
and t.targetLang = ?
Image.setString(2, langID); // either '3' or 'targetLang'
但我不确定我完全理解你的描述.数字是否代表您要比较的列的位置?和t.targetLang在同一行?如果是这样,我仍然认为你不需要子查询.您可以使用如下表达式:
where i.userID = ? And i.translated = 0
and FIELD(t.targetLang, t.targetLang, t.column2, t.column3, t.column4) = ?
Image.setString(2, '1'); // for the case where you allow all langs
Image.setString(2, '3'); // for the case where you want to match a specific column.
请参阅MySQL中FIELD()函数的手册,该函数在表达式列表中搜索第一个参数.它返回匹配的字段的整数位置.
使用此方法,您可以传递希望t.targetLang匹配的位置,这样您就可以将动态部分作为值传递,而不是作为列名传递.它还允许您避免子查询.
如果我仍然弄错了并且不理解您的问题,请编辑原始问题并提供更多详细信息. SHOW CREATE TABLE translationChains会有所帮助.你也可以回答一些我必须做出假设的事情,例如:你试图将t.targetLang与同一行中另一列中的值匹配吗?
好的,现在我更了解你的目标了.这是一个执行您想要的查询:
SELECT i.imageID,theImage,translationRating
来自图像我
INNER JOIN TranslationChains t
ON t.imageId = i.imageid
在哪里i.userID =? AND i.translated = 0
和? IN(t.targetLang,’targetLang’)
您可以将第二个参数传递给与t.targetLang匹配的整数,或者传递与谓词中的值’targetLang’匹配的文字字符串’targetLang’.
但是,我不推荐这个解决方案,因为它可能不会很好地使用索引,它可能必须通过将字符串参数与整数列进行比较来执行类型转换.
当您想要匹配所有语言时,更好的做法是在WHERE子句中没有最后一个术语的情况下执行查询.也就是说,在您的应用程序中,仅在您希望查询获取特定语言时才有条件地附加该术语.否则,省略该术语并跳过Image.setString().
String sql = "SELECT i.imageID, theImage, translationRating
FROM Images i
INNER JOIN TranslationChains t
ON t.imageId = i.imageid
WHERE i.userID = ? AND i.translated = 0 ";
if (langId) {
sql += " AND ? IN (t.targetLang, 'targetLang')";
}
. . .
Image.setInt(1, userID);
if (langId) {
Image.setString(2, langID);
}
Image.executeQuery()