【问题标题】:SQL Query for a search function搜索功能的 SQL 查询
【发布时间】:2018-10-17 00:52:04
【问题描述】:

我想做一个包含多个 Java Swing 组件的搜索功能,用户可以通过(姓名/国籍/专业/经验)进行搜索,结果将显示在 Jtable 中。

我只在 SQL 查询中苦苦挣扎,好像用户只输入了一个“名称”,不会检索任何数据,因为它像这样(名称、空、空、空)进入数据库而我没有我的数据库中有任何空值。

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

希望你能理解我的问题。

我当前的 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;
}

【问题讨论】:

  • 您可以根据条件创建查询,例如如果国籍不为空,则将“AND (nationality LIKE '" + nationality+"')”附加到您的查询等等..
  • 根据您向我们展示的内容,即使您返回的值是 null 或为空,您也不会调整您的请求。此外,按照您编写的方式,所有条件都必须有效才能取回数据。

标签: java mysql sql swing jdbc


【解决方案1】:

让我们看看您的查询:

   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,生成的查询将是

   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。

【讨论】:

    【解决方案2】:

    下面的代码可能会给你预期的结果。

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

    试试这个

    【讨论】:

    • 您可以像这样构建一个查询,但不是添加引号和值,而是添加一个 ?让它由 PreparedStatement 执行。
    • 您在 name.isEmpty() 部分中缺少一个“AND”
    • @surfMan- 这里提问者没有提到任何具体的陈述。他需要提到preparedstatement
    • 非常感谢,但它给了我以下错误:线程“AWT-EventQueue-0”中的异常。请看一下我之前给出的整个查询的代码。
    • @Alya AWT(Abstract Window Toolkit) 似乎与 UI 相关的错误。在新问题中发布您的完整堆栈跟踪
    【解决方案3】:

    在这种情况下,您有两个解决方案:

    1. 检查值,如果不为空,则将该部分附加到查询中,否则忽略它
    2. 第二种解决方案,您可以检查查询中的值是否为空。

    我会给你一个关于第二个的例子,你可以使用NamedParameterStatement 它就像PrepapredStatement 以避免语法错误和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 是否为空或您传递的值之类的国籍,这样您就避免了空。


    一些很好的参考:

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-07-23
      • 1970-01-01
      • 1970-01-01
      • 2013-10-05
      相关资源
      最近更新 更多