Использование оператора CASE в предложении where с параметрами

#sql #oracle #obiee

#sql #Oracle #obiee

Вопрос:

Я создаю отчет oracle, в котором, если пользователь вводит true или false, соответствующие значения должны переходить в параметр. если пользователь вводит все, то и true, и false должны перейти к параметрам.

Я использовал следующие операторы case 3 способами. все они показывают ошибку пропущенного ключевого слова. не могли бы вы, пожалуйста, помочь мне решить эту проблему.

 WHERE "EngExec Status" = ((:eng_exec_status = 'True' and "EngExec Status" = 'True') 
                           OR (:eng_exec_status = 'False' AND "EngExec Status" = 'False') 
                           OR (:eng_exec_status = 'All' AND  ("EngExec Status" = 'True' OR "EngExec Status"= 'False')))
                         
WHERE "EngExec Status" IN (CASE 
                               WHEN (:eng_exec_status) = 'True' THEN "EngExec Status"= 'True'
                               WHEN (:eng_exec_status) = 'False' THEN "EngExec Status"= 'False'
                               ELSE "EngExec Status" IN ('True', 'False')  
                           END) 

WHERE "EngExec Status" IN (CASE 
                               WHEN (:eng_exec_status) = 'All' THEN "EngExec Status" IN ('True','False')
                               ELSE (:eng_exec_status)   
                           END)         
 

Комментарии:

1. Поскольку case является выражением , оно должно возвращать скаляр. Oracle не имеет логического типа данных, поэтому case не может возвращать "EngExec Status"= 'True'

2. И еще одна проблема: если он будет иметь логическое значение, что вы ожидаете получить для такого фильтра: where "EngExec Status" = "EngExec Status"= 'True' ?

Ответ №1:

Я предполагаю, что вы хотите что-то простое, например

 WHERE ( :eng_exec_status = 'All' )
   OR ( :eng_exec_status = "EngExec Status" )
 

Ответ №2:

Ваш первый фрагмент:

 WHERE "EngExec Status" = ((:eng_exec_status = 'True' and "EngExec Status" = 'True') 
                           OR (:eng_exec_status = 'False' AND "EngExec Status" = 'False') 
                           OR (:eng_exec_status = 'All' AND  ("EngExec Status" = 'True' OR "EngExec Status"= 'False')))
 

Сбой, как и у вас WHERE column_value = (<boolean_expression>) , и это недопустимый синтаксис. Вы можете просто удалить "EngExec Status" = в начале:

 WHERE (:eng_exec_status = 'True'  AND "EngExec Status" = 'True') 
OR    (:eng_exec_status = 'False' AND "EngExec Status" = 'False') 
OR    (:eng_exec_status = 'All'   AND ("EngExec Status" = 'True' OR "EngExec Status"= 'False'))
 

Второй фрагмент содержит CASE выражение:

 CASE 
WHEN (:eng_exec_status) = 'True' THEN "EngExec Status"= 'True'
WHEN (:eng_exec_status) = 'False' THEN "EngExec Status"= 'False'
ELSE "EngExec Status" IN ('True', 'False')  
END
 

Он должен иметь синтаксис:

 CASE WHEN comparison_expr THEN return_expr [...] ELSE expr END
 

И из документации:

Как для простых, так и для искомых CASE выражений все return_exprs они должны либо иметь один и тот же тип данных ( CHAR , VARCHAR2 , NCHAR , или NVARCHAR2 , NUMBER BINARY_FLOAT , или BINARY_DOUBLE ), либо все должны иметь числовой тип данных.

Ваши возвращаемые значения не имеют ни одного из этих типов данных, и вместо этого вы ввели выражение сравнения.

Oracle жалуется на «ошибку пропущенного ключевого слова», поскольку он ожидает либо WHEN , ELSE либо END ключевые слова после "EngExec Status" в THEN ELSE предложениях and (поскольку недопустимо помещать выражение сравнения в это местоположение = , поэтому операторы IN and и выражение, следующее за ними, являются недопустимым синтаксисом).


Ваш третий фрагмент завершается ошибкой по той же причине, что и второй.


Если у вас есть CHECK ограничение для "EngExec Status" столбца, чтобы ограничить значение либо 'True' или 'False' , тогда вы можете упростить WHERE фильтр до:

 WHERE :eng_exec_status = "EngExec Status" OR :eng_exec_status = 'All'
 

Если у вас нет CHECK ограничения для ограничения значений, вы можете использовать:

 WHERE "EngExec Status" IN ('True', 'False')
AND   (:eng_exec_status = "EngExec Status" OR :eng_exec_status = 'All')