使用/ Java进行动态SQL查询

时间:2013-03-13 11:46:55

标签: java mysql sql dynamic-sql

我正在编写一个从数据库中获取记录的程序。我想基于3个变量(studentID,firstName和/或lastname)创建动态查询。这是我的java代码,它返回记录:

result = statement.executeQuery("SELECT * FROM student "
        + "WHERE (studentID = "
        + getStudentId() + " AND " + getStudentId() + " <> 0)"
        + " OR (firstName = '"
        + getFirstName() + "' AND '" + getFirstName() + "' IS NOT NULL)"
        + " OR (lastName = '"
        + getLastName() + "' AND '" + getLastName() + "' IS NOT NULL)");

我希望搜索根据存在的变量返回模糊到具体的结果。目前,如果studentID是唯一提供的字段,则返回该单个记录,或者如果studentID不存在但firstName为,则返回firstName的所有记录(如果仅存在变量,则返回lastName)。不起作用的是,如果我提供firstName和lastName,它将返回所有带有firstName的记录,而不管记录的姓氏如何,以及所有带有lastName的记录,无论名字是什么。示例firstName =“Bill”和lastName =“Jackson”:

1  Bill Hader
2  Steve Jackson
3  Bill Jackson
4  Bill Stewart
5  Denise Jackson
6  Wendy Jackson
7  Bill Matthews

我想弄清楚的是,如果我提供特定条件,例如firstName和lastName,如何获取包含指定的名字和姓氏的特定记录。

2 个答案:

答案 0 :(得分:1)

A)这应该可以解决问题:

String query = "SELECT * FROM student WHERE (studentID=? OR ?=0) 
                                        AND (firstName=? OR ? IS NULL)
                                        AND (lastName =? OR ? IS NULL)";
ps.setInt(1,getStudentID());
ps.setString(2,getFirstName());
ps.setString(3,getFirstName());
result ps.executeQuery();

请注意,逻辑与您发布的内容相反。在您的代码中,如果studentId0firstName为空,则您有:

(studentID=0 AND 0<>0) OR (firstName='null' OR null IS NOT NULL)

false。相反,您需要指定

(studentID=0 OR 0=0) AND (firstName='null' OR null IS NULL)

B)如果你想要Java中的条件逻辑:

String query = "SELECT * FROM student WHERE (";
if (getStudentId()!=0) query+="studentID=? AND";
if (getFirstName()!=null) query+="firstName=? AND";
if (getLastName ()!=null) query+="lastName=?  AND";
query+=" 1=1)";
PreparedStatement ps = connection.prepare(query);
if (getStudentId()!=0)    ps.setInt(1,getStudentID());
if (getFirstName()!=null) ps.setString(2,getFirstName());
if (getLastName ()!=null) ps.setString(3,getFirstName());
result ps.executeQuery();

答案 1 :(得分:0)

因此,假设您的标准为0,'Bill'和'Jackson',这是您将要执行的查询:

select *
from student
where 
   (studentID = 0 and 0 <> 0)
or (firstName = 'Bill' and 'Bill' is not null)
or (lastName = 'Jackson' and 'Jackson' is not null)

where条款中有三个条件。第一个(再次,假设你输入0)将不匹配任何东西。第二个将匹配firstName为'Bill'的所有记录。第三个将匹配lastName为'杰克逊'的所有记录。由于您的条件由or运算符连接,因此结果集(查询结果)将是所有匹配集的并集,因此任何firstName为'Bill'或其lastName的记录是'杰克逊',因此你所有的样本记录。如果您想将此限制为只有一个名字和姓氏,请将or更改为and并简化查询:

select *
from student
where 
    firstName = 'Bill' 
and lastName = 'Jackson'

您似乎试图在单个where子句中构建太多逻辑。现在,怎么办呢?让我们单独留出studentID字段一分钟,所以我们只想匹配确切的名字(如果提供了一个)和确切的姓氏(如果有的话)。我们可以这样做:

select *
from student
where
    (firstName = ? or ? is null)
and (lastName =  ? or ? is null)

最后,您似乎想要的另一个条件是,如果提供学生ID,我们会将结果限制为仅该ID。我们可以这样做:

select *
from student
where
    (studentID = ? and ? <> 0)
or (
      (firstName = ? or ? is null)
  and (lastName =  ? or ? is null)
)

为简单起见,假设我们始终返回与给定学生ID匹配的行,即使名字或姓氏不匹配也是如此。 (因此运行参数1,'比尔','杰克逊'将产生两个记录)。如果您想要使用studentID删除任何与所有三个条件都不匹配的记录,请将查询更改为:

select *
from student
where
    (studentID = ? or ? = 0)
and  (
      (firstName = ? or ? is null)
  and (lastName = ? or ? is null)
)

Here's a SQLFiddle展示它是如何运作的。

正如其他人所提到的,请学习如何在Java中使用参数化查询。这并不难。