所以我有4个菜单选项(产品,位置,courseType和类别),所有这些都可以为null(使用JSF编程,但这应该与此问题无关,因为它是一个SQL问题)。
菜单选择将向托管bean发送用户选择的变量,并使用预准备语句使用用户选择的菜单中的信息(如果有)搜索数据库表。
如果用户将菜单项保留为null,则应搜索所有内容。
如果用户将1或2或3个菜单项留下信息,而另一个留空,则应进行相应的搜索。
我的问题是如何在没有附加到适当的sql语句的bean中的一堆if / then语句的情况下执行此操作?
或者是否有一个更好的sql语句我可以做到这一切吗?
我在Java中使用预备语句。
我试过了:
if (product != null && location != null && courseType != null && category != null) {
pstmt = conn.prepareStatement("select * FROM Courses WHERE "
+ "product = ? "
+ "and location = ? "
+ "and courseType = ? "
+ "and category = ?");
pstmt.setString(1, product);
pstmt.setString(2, location);
pstmt.setString(3, courseType);
pstmt.setString(4, category);
} else if (product == null && location != null && courseType != null && category != null) {
pstmt = conn.prepareStatement("select * FROM Courses WHERE "
+ "location = ? "
+ "and courseType = ? "
+ "and category = ?");
pstmt.setString(1, location);
pstmt.setString(2, courseType);
pstmt.setString(3, category);
}
等等但是我必须这样做16次,因为每个1的情况是空的而不是其他情况? 必须有一个更聪明的方法(通过使用1个sql语句或只有几个java if / then语句?)
感谢Luiggi Mendoza!我的代码是这样的:
pstmt = conn.prepareStatement("select * FROM Courses WHERE "
+ "(product = ? or ? is null) "
+ "and (location = ? or ? is null) "
+ "and (courseType = ? or ? is null)"
+ "and (category = ? or ? is null)");
pstmt.setString(1, product);
pstmt.setString(2, product);
pstmt.setString(3, location);
pstmt.setString(4, location);
pstmt.setString(5, courseType);
pstmt.setString(6, courseType);
pstmt.setString(7, category);
pstmt.setString(8, category);
rset = pstmt.executeQuery();
更新是的我必须使用=“”而不是null为不同的mysql数据库(可能是不同的版本或其他东西)
答案 0 :(得分:7)
我假设您NULL
所选值的默认值(因为我不知道使用PreparedStatement
的另一种方式)作为'0'
(仅作为示例) )。
知道这一点,我倾向于使用这种SQL:
SELECT *
FROM Courses
WHERE
(product = ? or ? = '0')
and (location = ? or ? = '0')
and (courseType = ? or ? = '0')
and (category = ? or ? = '0')
使用此方法,您可以利用IF
用法并让数据库处理工作。唯一不好的一点是,你应该将每个变量设置两次(这一生中没有任何东西是自由的=)。
create table pruebaMultiSelect
(id int primary key auto_increment,
nombre varchar(50),
tipo varchar(10),
categoria varchar(10));
insert into pruebaMultiSelect values
(null, 'Luiggi', 'A', 'X');
insert into pruebaMultiSelect values
(null, 'Thomas', 'A', 'Y');
insert into pruebaMultiSelect values
(null, 'Jose', 'B', 'X');
insert into pruebaMultiSelect values
(null, 'Trina', 'B', 'Y');
现在,相关的Java代码:
public class DBTest {
public void testPreparedStatement(String p1, String p2) throws SQLException {
Connection con = null;
PreparedStatement pstmt = null;
ResultSet rs = null;
try {
con = getConnection();
pstmt = con.prepareStatement("SELECT * FROM pruebaMultiSelect WHERE (tipo = ? OR ? = 'EMPTY') "
+ "AND (categoria = ? OR ? = 'EMPTY')");
pstmt.setString(1, p1);
pstmt.setString(2, p1);
pstmt.setString(3, p2);
pstmt.setString(4, p2);
rs = pstmt.executeQuery();
while (rs.next()) {
System.out.printf("%5d %15s\n", rs.getInt(1), rs.getString(2));
}
} catch(ClassNotFoundException e) {
e.printStackTrace();
} finally {
rs.close();
pstmt.close();
con.close();
}
}
public Connection getConnection() throws SQLException, ClassNotFoundException {
Class.forName("com.mysql.jdbc.Driver");
return DriverManager.getConnection("jdbc:mysql://localhost:3306/luiggi_test", "user", "password");
}
public static void main(String[] args) throws SQLException {
//this will return all the data
String p1 = "EMPTY";
String p2 = "EMPTY";
new DBTest().testPreparedStatement(p1, p2);
}
}
使用MySQL 5.1.18进行测试。
答案 1 :(得分:1)
我倾向于使用这样的辅助方法构建动态查询:
StringBuilder query = new StringBuidler();
query.append("SELECT foo, bar FROM baz");
query.append(buildProductClause(product));
query.append(buildLocationClause(location));
query.append(buildCourseTypeClause(courseType));
// etc...
如果您仍想使用预准备语句,可以使用成员字段构建参数数组。