Альтернатива для COALESCE, когда все его параметры равны нулю - PullRequest
0 голосов
/ 20 ноября 2018

Я занимаюсь разработкой веб-приложения (проект java-maven), и возникла проблема с запросом, который я использую.Пользовательский интерфейс моего веб-приложения имеет 2 поля поиска: PTT и ID.Пользователь должен заполнить хотя бы одно из полей, чтобы выполнить поиск.Так что оба поля обнуляются, но не одновременно.Раньше у меня было только одно поле: PTR, и оно показывало массив результатов размером 52. (также получая то же число, если я выполню select * from users where ptr='smthing').После этого я добавил поле ID и обновил свой запрос следующим образом:

Я выполняю этот запрос в своем веб-сервисе:

String query= "SELECT t.ptr, t.id ";
        query+= "FROM users t ";
        query+= "WHERE t.ptr = COALESCE(?, t.ptr) AND " ;
        query+= "t.id = COALESCE(?, t.id) ";

и задаю поля с помощью подготовленного оператора.

Теперь, если поле ptr заполнено, но поле id оставлено пустым (это может быть нулевая или пустая строка) в пользовательском интерфейсе, и пользователь выполняет поиск, размер массива результатов становится равным 30. Я сравнил сбазы данных, и он не выбирает строки, где ID является нулем.Так что coalesce не то, что мне нужно, когда оба его параметра (?, T.ptr) равны нулю.Как я могу решить эту проблему, какие-либо предложения?

Ответы [ 3 ]

0 голосов
/ 20 ноября 2018

Проверьте это утверждение:

String query= "SELECT t.ptr, t.id ";
query+= "FROM users t ";
query+= "WHERE (t.ptr = ? OR 1 = ?)" 
query+= " AND " ;
query+= "(t.id = ? OR 1 = ?)";

Вы видите, что для каждого из t.id и t.ptr есть соответствующий параметр.Всего будет 4 параметра.Вы говорите, что по крайней мере 1 из t.id или t.ptr имеет допустимое значение, поэтому есть 2 случая: [1] t.id и t.ptr оба имеют допустимые значения.Для обоих параметров партнера вы передаете 0, и запрос становится:"SELECT t.ptr, t.id FROM users t WHERE (t.ptr = valueptr OR 1 = 0) AND (t.id = valueid OR 1 = 0)"В ГДЕ часть:t.ptr = valueptr OR 1 = 0 эквивалентно t.ptr = valueptr, иt.id = valueid OR 1 = 0 эквивалентно t.id = valueid,и запрос, наконец, становится:"SELECT t.ptr, t.id FROM users t WHERE t.ptr = valueptr AND t.id = valueid" [2] из t.id или t.ptr только одно имеет допустимое значение, допустим, это t.ptr.Для аналога t.ptr вы передаете 0, для t.id вы передаете -1 (или любое другое несуществующее значение), а для аналога t.id вы передаете 1, и запрос становится:"SELECT t.ptr, t.id FROM users t WHERE (t.ptr = valueptr OR 1 = 0) AND (t.id = -1 OR 1 = 1)"В ГДЕ часть:t.ptr = valueptr OR 1 = 0 эквивалентно t.ptr = valueptr, иt.id = -1 OR 1 = 1 эквивалентно true, потому что 1 = 1 всегда true,и запрос, наконец, становится:"SELECT t.ptr, t.id FROM users t WHERE (t.ptr = valueptr OR 1 = 0)"эквивалентно:"SELECT t.ptr, t.id FROM users t WHERE (t.ptr = valueptr)"(В случае, когда только t.id имеет допустимое значение, вы передаете недопустимое значение для t.ptr и 1 для его аналога и для аналога, если t.id вы передаете 0.)Может быть, это кажется сложным, но оно работает и может быть расширено более чем на 2 столбца.

0 голосов
/ 20 ноября 2018

Oracle имеет функцию сборки для этого.Но трудно понять, как его использовать.

lnnvl(a = b) = true if (a != b ) or ( a = null ) or (b = null)

в вашем случае

WHERE lnnvl(t.ptr != ? ) AND lnnvl( t.id != ?)

LNNVL

0 голосов
/ 20 ноября 2018

Я думаю, что вам нужна логика:

WHERE (t.ptr = ? OR ? IS NULL) AND 
      (t.id = ? OR ? IS NULL)

Я бы порекомендовал использовать именованные параметры, чтобы вам не приходилось передавать их дважды.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...