1

我正在编写一个从数据库中获取记录的程序。我想创建一个基于 3 个变量(学生 ID、名字和/或姓氏)的动态查询。这是我返回记录的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

我想弄清楚的是,如果我提供特定的标准,例如名字和姓氏,如何获取包含指定的名字和姓氏的一个特定记录。

4

3 回答 3

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();
于 2013-03-13T12:10:06.860 回答
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为“比尔”或lastName“杰克逊”,因此是所有样本记录。如果您想将其限制为只有一个名字和姓氏,请将您的更改or为 anand并简化查询:

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、'Bill'、'Jackson' 运行将产生两条记录)。如果您想使用studentID删除不符合所有三个条件的任何记录,请将查询更改为:

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

这是一个 SQLFiddle来展示它是如何工作的。

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

于 2013-03-13T12:22:58.977 回答
0

使用此问题中所示的查询构建器 API可能是完成复杂动态 SQL的最佳方式。用于构建动态 SQL 的流行 API 有:

用于构建动态 JPQL 的流行 API 有:

使用 jOOQ 解决您的问题的示例是:

Condition condition = DSL.trueCondition();
if (getStudentId() != 0)
    condition = condition.and(STUDENT.STUDENTID.eq(getStudentId()));
if (getFirstName() != null)
    condition = condition.and(STUDENT.FIRSTNAME.eq(getFirstName()));
if (getLastName() != null)
    condition = condition.and(STUDENT.LASTNAME.eq(getLastName()));

Result<StudentRecord> result =
DSL.using(configuration)
   .selectFrom(STUDENT)
   .where(condition);

(免责声明:我为 jOOQ 背后的公司工作)

于 2018-05-11T09:48:59.067 回答