Oracle: истинное значение в ГДЕ - PullRequest
0 голосов
/ 08 ноября 2018

Я строю SQL-запрос внутри функции. Параметры функций являются моими критериями для предложения WHERE. Параметры также могут быть нулевыми.

foo (1,2,3)           =>   SELECT x FROM y WHERE a=1 AND b=2 AND c=3;
foo (null, 2, null)   =>   SELECT x FROM y WHERE b=2;

Мой подход к этому в коде заключается в добавлении самой первой истины за все время в предложении WHERE (например, 1 = 1 или NULL равно NULL или 2> 1)

Таким образом, мне не нужно решать проблему, состоящую в том, что первое условие WHERE находится после «WHERE», а все остальные - после «AND».

String sql="SELECT x FROM y WHERE 1=1";
if (a!=null)
{
  sql += " AND a="+a;
}

Есть ли лучший термин, чем 1 = 1, или другие мои образцы, чтобы ИСКЛЮЧИТЕЛЬНО иметь всегда истинное значение? TRUE и FALSE не работают.

Ответы [ 6 ]

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

Oracle не поддерживает логический тип в SQL. Он существует в PL / SQL, но не может использоваться в запросе. Самое простое, что нужно сделать, это 1 = 1 для true и 0 = 1 для false. Я не уверен, оптимизатор оптимизирует их или нет, но я подозреваю, что влияние на производительность незначительно. Я использовал это, где число предикатов неизвестно до времени выполнения.

Я думаю, что эта конструкция превосходит все, что использует nvl, coalesce, decode или case, потому что они обходят нормальные индексы, и у меня они есть, приводят к сложным и медленным планам выполнения.

Итак, да, я бы сделал что-то вроде вас (не уверен, на каком языке вы строите этот запрос; это недопустимый PL / SQL. Также вы должны использовать переменные связывания, но это уже другая история):

sql = "SELECT x FROM y WHERE 1=1";
if (a != null)
{
    sql += " AND a=" + a;
}
if (b != null)
{
    sql += " AND b=" + b;
}
... etc.

Я думаю, что это лучше, чем предложение Гордона Линоффа, потому что в противном случае это было бы более сложным, потому что вам пришлось бы иметь другое условие для каждой проверки предиката, если был предыдущий предикат, т. Е. Нужно ли было включать AND или нет. Это просто делает код более многословным, чтобы избежать одного, тривиального предложения в запросе.

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

Как насчет использования OR внутри скобок, в то время как AND s существует вне их

SELECT x 
  FROM y 
 WHERE ( a=:prm1 OR :prm1 is null) 
   AND ( b=:prm2 OR :prm2 is null) 
   AND ( c=:prm3 OR :prm3 is null);
0 голосов
/ 08 ноября 2018

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

Select 
decode(a, 1, x,null),
decode(b, 2, x,null),
decode(c, 3, x,null)
from y
0 голосов
/ 08 ноября 2018

В sql стандартным способом «по умолчанию null» является использование coalesce. Допустим, ваш ввод @ p1, @ p2 и @ p3

Тогда

 select *
 from table
 where a = coalesce(@p1,a) and 
       b = coalesce(@p2,b) and 
       c = coalesce(@p3,c)

Таким образом, если (в качестве примера) @ p1 равен нулю, он будет сравнивать a = a (что всегда верно). Если @ p1 не равно нулю, он будет фильтровать по равному этому значению.

Таким образом, null становится «подстановочным знаком» для всех записей.

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

используйте NVL, чтобы вы могли установить значение по умолчанию. Посмотрите на NVL или NVL2. Либо может работать на вас. проверить: http://www.dba -oracle.com / t_nvl_vs_nvl2.htm

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

Я никогда не понимал подход к обязательному предложению where, даже если нет условий. Если вы строите логику, то объедините условия. Если полученная строка пуста, то полностью пропускает предложение where .

Многие языки приложений имеют эквивалент concat_ws() - конкатенация строк с разделителем (например, join в Python). Таким образом, исключение предложения where даже не приводит к гораздо более сложному коду.

Что касается вашего вопроса, Oracle не имеет логических значений, поэтому 1=1, вероятно, является наиболее распространенным подходом.

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