用于搜索功能的SQL查询

3

我想使用多个Java Swing组件实现搜索功能,用户可以按照(姓名/国籍/专业/经验)进行搜索,并在Jtable中显示结果。

enter image description here

我只有在SQL查询方面遇到了困难,因为如果用户只输入了“姓名”,则不会检索到任何数据,因为它会像这样进入数据库(name,null,null,null),而我的数据库中没有任何空值。

因此,我希望检索所有具有该名称的数据,而不考虑其他列,但同时,如果他们选择了特定的专业,例如,我希望检索所有具有所选名称和专业的数据,以此类推。

我希望您理解我的问题。

我目前的SQL语句:

public ArrayList<Applications> getData(String name, String nationality, String specialty, String experience) {

   ArrayList<Applications> list = new ArrayList<Applications>();
   Connection con = getConnection();
   Statement st;
   ResultSet rows;

   try {
       st = con.createStatement();

       rows = st.executeQuery("SELECT * FROM applications WHERE name LIKE '%" +  name+"%'"
            + " AND (nationality LIKE '" +  nationality+"')"
            + " AND (specialty LIKE '" +  specialty+"')"
            + " AND (experience LIKE '" +  experience+"')");

       Applications applications;

       while(rows.next()) {
           applications = new Applications(
               rows.getInt("id"),
               rows.getString("name"),
               rows.getString("nationality"),
               rows.getString("Specialty"),
               rows.getString("experience")
           );

          list.add(applications);
       }   
   } catch (SQLException ex) {
       Logger.getLogger(MyQuery.class.getName()).log(Level.SEVERE, null, ex);
   }

   return list;
}

1
你可以根据条件创建查询,比如如果国籍不为空,则在查询中添加 "AND (nationality LIKE '" + nationality+"')" 等等。 - Ankur
从你展示给我们的内容来看,即使你收到的值是null或空值,你也没有适应你的请求。此外,按照你的写法,所有条件都必须有效才能检索数据。 - DamCx
3个回答

2

让我们来看看你的查询:

   rows = st.executeQuery("SELECT * FROM applications WHERE name LIKE '%" +  name+"%'"
        + " AND (nationality LIKE '" +  nationality+"')"
        + " AND (specialty LIKE '" +  specialty+"')"
        + " AND (experience LIKE '" +  experience+"')");

这里,由于只给出了name,其他值都为null。如果您编写此代码进行测试:

String foo = null;
System.out.println(foo + "");

输出结果将是

"null"

因此,由于您的值为 null,生成的查询将是

   SELECT * FROM applications WHERE name LIKE '%Rowan Atkinson%'
        AND (nationality LIKE 'null')
        AND (specialty LIKE 'null')
        AND (experience LIKE 'null')

首先,让我们确保在出现null的情况下,您会得到一个空的String
   rows = st.executeQuery("SELECT * FROM applications WHERE name LIKE '%" +  ((name == null) ? "" : name)+"%'"
        + " AND (nationality LIKE '" +  ((nationality == null) ? "" : nationality)+"')"
        + " AND (specialty LIKE '" +  ((specialty == null) ? "" : specialty)+"')"
        + " AND (experience LIKE '" +  ((experience == null) ? "" : experience)+"')");

下一个问题是你只在name处放置了%,这也是不正确的,因此让我们修复它:
   rows = st.executeQuery("SELECT * FROM applications WHERE name LIKE '%" +  ((name == null) ? "" : name)+"%'"
        + " AND (nationality LIKE '%" +  ((nationality == null) ? "" : nationality)+"%')"
        + " AND (specialty LIKE '%" +  ((specialty == null) ? "" : specialty)+"%')"
        + " AND (experience LIKE '%" +  ((experience == null) ? "" : experience)+"%')");

现在请阅读 YCF_L 的答案,这样您就可以使用 PreparedStatement 的命名参数。


1
以下代码可能会给您期望的结果。
StringBuilder sql=new StringBuilder("SELECT * FROM applications WHERE 1=1 ");
        if(!name.isEmpty()){
            sql.append(" AND name LIKE '%" +  name+"%'");
        }
        if(!nationality.isEmpty()){
            sql.append(" AND (nationality LIKE '" +  nationality+"')");
        }
        if(!specialty.isEmpty()){
            sql.append(" AND (specialty LIKE '" +  specialty+"')");
        }
        if(!experience.isEmpty()){
            sql.append(" AND (experience LIKE '" +  experience+"')");
        }

        rows = st.executeQuery(sql.toString());

试试这个


2
你可以构建一个像这样的查询语句,但是不要添加引号和值,而是添加一个 ?,以便由 PreparedStatement 执行。 - SurfMan
在 name.isEmpty() 部分缺少一个 "AND"。 - SurfMan
@surfMan- 这里的提问者没有提到任何具体的语句。他需要提到preparedstatement。 - Keval Pithva
非常感谢您,但它给了我以下错误:Exception in thread "AWT-EventQueue-0"。请看一下我的之前的代码,我已经提供了整个查询。 - Alya
@Alya AWT(抽象窗口工具包)似乎是与用户界面相关的错误。请在新问题中发布完整的堆栈跟踪。 - Keval Pithva

1
在这种情况下,您有两个解决方案:
  1. 检查值是否不为空,如果是,则将该部分附加到查询中,否则忽略它
  2. 第二种解决方案是在查询中检查该值是否为空。
我将为您提供第二个解决方案的示例,您可以使用NamedParameterStatement,它类似于PreparedStatment,以避免语法错误和SQL注入。
String query = "SELECT * FROM applications"
        + " WHERE (:name is null or name LIKE CONCAT('%', :name, '%')) "
        + " AND (:nationality is null or nationality LIKE :nationality)"
        + " AND (:specialty is null or specialty LIKE :specialty)"
        + " AND (:experience is null or experience LIKE :experience)";

NamedParameterStatement namedParametterStatement = 
                           new NamedParameterStatement(connection, query);

namedParametterStatement.setString("name", name);
namedParametterStatement.setString("nationality", nationality);
namedParametterStatement.setString("specialty", specialty);
namedParametterStatement.setString("experience", experience);

请注意这里的示例技巧:

(:nationality is null or nationality LIKE :nationality)

它将检查 nationality 是否为空或者是否与您传递的值相同,这样可以避免出现空值。

一些好的参考资料:


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