【问题标题】:Dynamic SQL Query w/ Java使用 Java 的动态 SQL 查询
【发布时间】:2023-04-11 06:54:01
【问题描述】:

我正在编写一个从数据库中获取记录的程序。我想创建一个基于 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

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

【问题讨论】:

标签: java mysql sql dynamic-sql


【解决方案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();

请注意,逻辑与您发布的内容相反。在您的代码中,如果 studentId0 并且 firstName 是 null,那么您有:

(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();

【讨论】:

  • 谢谢。我不知道我在寻找什么被称为准备好的声明。我现在正在从 oracle 的网站上阅读此内容。
【解决方案2】:

因此,假设您的条件是 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 为“Jackson”的记录。因为您的条件由or 运算符连接,所以结果集(查询结果)将是所有匹配集的并集,因此任何firstName 为“Bill”或lastName 为“Jackson”的记录,因此您的所有样本记录。如果您想将其限制为只有一个名字和姓氏,请将您的 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、'Bill'、'Jackson' 运行将产生两条记录)。如果您想使用 studentID 删除不符合所有三个条件的任何记录,请将查询更改为:

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

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

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

【讨论】:

  • 谢谢!我已经学习了大约一个月,编程不是我的强项,但我感谢所有这些帮助。
【解决方案3】:

使用query builder API as illustrated in this question 可能是完成复杂dynamic 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-06-14
    • 1970-01-01
    • 1970-01-01
    • 2012-12-21
    • 2012-01-12
    • 2021-10-10
    • 2020-01-19
    • 1970-01-01
    相关资源
    最近更新 更多