Попытка поиска частично совпадающих атрибутов - PullRequest
0 голосов
/ 19 марта 2020

Итак, я пытаюсь сделать запрос (Java) к базе данных (h2) для функции поиска. Для поиска в Запросе должны быть найдены записи, в которых атрибуты частично совпадают.

Поиск может быть для каждой комбинации атрибутов, поэтому проверьте, действительны ли они.

  • getName () возвращает String
  • getDescription () возвращает String
  • getBreed () возвращает String
  • getRanking () возвращает целое число
  • getBirthdate ( ) возвращает объект LocalDateTime в базе данных, это дата, остальные имеют тот же тип данных в базе данных.

    @Override
    
public List<Horse> search(Horse mockHorse) {
    LOGGER.trace("Search horses which match{}", mockHorse);
    String query = "SELECT * FROM " + TABLE_NAME + " WHERE" +
        "(UPPER(name) LIKE UPPER(%?%)) AND "+
        "UPPER(description) LIKE UPPER(%?%)"+
        " AND breed LIKE ? AND ranking=?";
    // set value to wildcard to match every value
    if (!mockHorse.getBreed().equals("")) {
        mockHorse.setBreed("%");
    }

(извините за тот формат, который не был принять это иначе)

    Object[] obj = new Object[]{
        mockHorse.getName(),
        mockHorse.getDescription(),
        mockHorse.getBreed(),
        mockHorse.getRanking()
    };

    if (!(mockHorse.getBirthdate()==null)){
        query+= " AND birthdate <=?";
        obj = new Object[] {
            mockHorse.getName(),
            mockHorse.getDescription(),
            mockHorse.getBreed(),
            mockHorse.getRanking(),
            mockHorse.getBirthdate().toString()
        };
    }

    final String sql = query +';';
    return jdbcTemplate.query(sql,obj, this::mapRow);
}

Однако, что бы я ни пытался исправить, я получаю только новые ошибки, в настоящее время я застрял с

Syntax error in SQL statement "SELECT * FROM HORSE WHERE(UPPER(NAME) LIKE UPPER(%[*]?%)) AND UPPER(DESCRIPTION) LIKE UPPER(%?%) AND BREED LIKE ? AND RANKING=? AND BIRTHDATE <=?;"; expected "), NOT, EXISTS, INTERSECTS, UNIQUE"; SQL
statement:
SELECT * FROM Horse WHERE(UPPER(name) LIKE UPPER(%?%)) AND UPPER(description) LIKE UPPER(%?%) AND breed LIKE ? AND ranking=? AND birthdate <=?; [42001-200]

Не могли бы вы дать мне подсказку о том, что я делаю не так. (Я попытался удалить 'из UPPER, а также переместить их в сторону от UPPER (' UPPER ') и обернуть его вокруг% (UPPER ('%?% ')).

Ответы [ 2 ]

0 голосов
/ 19 марта 2020
  1. Вам необходимо использовать '%' || ? || '%' вместо %?%.

  2. UPPER. Эмулируется без учета регистра LIKE, но такая эмуляция не может правильно обрабатывать некоторые национальные буквы, не каждая буква имеет отображение 1: 1 между вариантами строчных и прописных букв. Вместо этого лучше и проще использовать ILIKE:

name ILIKE '%' || ? || '%'
Если ваш параметр может содержать _ или %, вам нужно экранировать их с помощью некоторого символа и добавить выражение ESCAPE к LIKE / ILIKE:
name ILIKE '%' || REGEXP_REPLACE(?, '([_%\\])', '\\$1') || '%' ESCAPE '\'

В коде Java необходимо ввести \\, чтобы получить \ в строке (\\\\ для \\). Если _ и % не используются в ваших параметрах, вам не нужно это дополнительное преобразование.

У вас есть два места, где ваш SQL должен быть исправлен.

0 голосов
/ 19 марта 2020

Проблема в ваших where условиях.

WHERE
    (UPPER(NAME) LIKE UPPER(%[*]?%)) 
    AND UPPER(DESCRIPTION) LIKE UPPER(%?%) 
    AND BREED LIKE ? 
    AND RANKING = ? 
    AND BIRTHDATE <=?

Первые два условия недействительны SQL. Если вы хотите выполнить конкатенацию параметров в виде строк поиска в запросе, вы должны иметь:

WHERE
    UPPER(NAME) LIKE CONCAT('%[*]', UPPER(?), '%') 
    AND UPPER(DESCRIPTION) LIKE CONCAT('%', UPPER(?), '%') 
    AND BREED LIKE CONCAT('%', ?, '%')
    AND RANKING = ? 
    AND BIRTHDATE <=?

Примечание: поскольку фильтр на BREED использует LIKE, я предположил, что вам нужны здесь шаблоны тоже.

Альтернативой может быть создание сцепленных строк в вашем приложении. Это должно быть небольшое усилие на стороне приложения, и наборы для уборщика SQL код:

WHERE
    UPPER(NAME) LIKE ?
    AND UPPER(DESCRIPTION) LIKE ?
    AND BREED LIKE ?
    AND RANKING = ? 
    AND BIRTHDATE <=?
...