如何将“变量”注入到查询的WHERE子句中?

3
我有一个问题: SELECT * FROM table_name WHERE name=? surname=? gender=?; 我需要将字符串注入到查询中(我使用预处理语句),但问题是这3个子句都是可变的。根据用户输入,它们可能都不活动,也可能只有1或2个活动。
如果用户没有为其输入任何内容,如何“忽略”它们?
感谢大家!
编辑:如果有人知道如何将setString()设置为PreparedStatement,而不让他在字符串周围放置' ',那么也很好。

动态 SQL 胜利。 - Brian Driscoll
要么准备所有七种可能的组合(如果没有子句也是一个选项,则为8),要么动态构建查询。 - RealSkeptic
2
可能是具有动态where子句的预处理语句的重复问题。 - Arnaud
看一下这个条件。顺便说一句,下面的解决方案是可行的。 - Zorglube
如果您可以使用setString()而不需要在值周围加引号,那么它将无法防止注入攻击。任何人都可以使用像true; drop table table_name; --这样的值。 - RealSkeptic
2个回答

3
最简单的解决方案是动态构建您的预处理语句,类似于以下内容:
String sql = "SELECT * FROM table_name";

if (nameInput != null || surnameInput != null || genderInput != null)
{
    sql += " WHERE ";
}

if (nameInput != null)
{
    sql += "name=? ";
}

我认为您可以从其他输入中了解到这个想法。

然后,您可以将sql的最终值与输入值一起传递到prepare调用中。


抱歉,我看到了[mysql]标签,下意识地用PHP编写了我的答案。我希望我尝试使用Java是可以的(至少在你能理解它的意义上)。 - Brian Driscoll
但是这种方式是可注入的!我想要防止它(这就是为什么我使用带有setString()的preparedStatement) - Claudio
1
@ClaudioCiociola 这不是可注入的,因为您动态构建了查询骨架,但只将用户的值添加到准备好的语句中。 - RealSkeptic
1
@ClaudioCiociola 它并不比你已经拥有的更可注入。 - Brian Driscoll
2
这不容易受到恶意SQL注入的攻击,但你仍然需要准备语句,在将其发送到数据库之前在Java中有条件地构建语句。一个小技巧是,当我做这样的事情时,我倾向于添加“WHERE 1 = 1”作为初始子句,这样我就知道任何进一步的谓词应该是“AND Col =?”而且不需要检查它是否是第一个谓词,应该以“WHERE”而不是“AND”开头。 - GarethD

1

只需一行简单的代码,不需要复杂或昂贵的逻辑...

假设您的三个变量是@name、@surname和@gender。

同时假设当不需要筛选时会提供一个零长度字符串。

那么,您的Select语句只需如下:

    select * from table_name where (name = @name or @name = '') and (surname = @surname or @surname = '') and (gender = @gender or @gender = '')

就是这样!没有复杂或昂贵的逻辑。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接