Oracle SQL использует Coalesce - PullRequest
1 голос
/ 25 августа 2009

У меня есть этот запрос, который работает в Oracle, но я хочу преобразовать его в Coalesce из-за некоторых проблем с Visual Studio.

SELECT * 
FROM a Left Join b on b.institution_code=a.institution_code
WHERE 
      (upper(a.Login_Name)=UPPER('%' || :Login_Name || '%') OR :Login_Name IS NULL)
  AND (upper(a.Display_Name) Like  UPPER('%' || :Display_Name || '%')   OR :Display_Name IS NULL) 
  AND (upper(a.Email_Address)=UPPER(:Email_Address) OR :Email_Address IS NULL) 
  AND ((a.institution_code=:institution_code) OR :institution_code IS NULL)  
  AND (upper(b.institution_desc) Like  UPPER('%' || :institution_desc || '%')   OR :institution_desc IS NULL)

Это работает

WHERE
Upper(a.Display_Name) LIKE Upper('%' || COALESCE(:Display_Name,a.Display_Name) || '%')
AND upper(a.Login_Name)=Upper(COALESCE(:Login_Name,a.Login_Name))    
AND upper(a.Email_Address)=Upper(COALESCE(:Email_Address,a.Email_Address))

но когда я пытаюсь преобразовать поле institu_code и institu_desc для использования coalesce, я не получаю никаких результатов от запросов.

когда я добавляю эти строки, нет результатов

    AND a.institution_code=COALESCE(:institution_code,a.institution_code)
  AND (Upper(b.institution_desc) LIKE Upper('%' || COALESCE(:institution_desc,b.institution_desc) || '%'))

Ответы [ 3 ]

2 голосов
/ 25 августа 2009
AND ((a.institution_code=:institution_code) OR :institution_code IS NULL)

не эквивалентно

AND a.institution_code=COALESCE(:institution_code,a.institution_code)

ЕСЛИ a.institution_code IS NULL и: institu_code IS NULL, то первый пример будет истинным (потому что вторая часть ИЛИ истинна), а второй - нет (поскольку NULL = NULL не истинно). 1005 *

1 голос
/ 25 августа 2009
WHERE (UPPER(a.Login_Name) = UPPER('%' || :Login_Name || '%') OR :Login_Name IS NULL)

... должно быть:

WHERE (:Login_Name IS NULL OR UPPER(a.Login_Name) = UPPER('%' || :Login_Name || '%'))

Вы хотите проверить переменную связывания FIRST - в противном случае вы выполняете сравнение данных, прежде чем узнаете, что все равно хотите. Вы получаете наихудшую возможную производительность из запроса.

Далее, если вы собираетесь запускать UPPER для нескольких столбцов - используйте Факторинг подзапроса, чтобы он выполнялся первым:

WITH upper_a AS (
SELECT a.pk,
       UPPER(a.login_name) 'login_name',
       UPPER(a.display_name) 'display_name',
       UPPER(a.email_address) 'email_address',
       UPPER(b.institution_desc) 'institution_desc'
  FROM a)
SELECT *
  FROM A a
  JOIN upper_a ua ON ua.pk = a.pk
 WHERE :Login_Name IS NULL OR ua.login_name = v_login_name

Oracle плохо работает WHERE (параметр равен NULL ИЛИ t.col = параметр), и вы ничего не получите, используя переменные связывания для параметров с необязательными значениями. То, что вы действительно хотите использовать, это переменные CONTEXT (доступно с 9i).

0 голосов
/ 25 августа 2009

Я подозреваю, что проблема во 2-й строке (b.institution_desc). В частности, у вас есть возможность для ситуации NULL LIKE NULL, а NULL LIKE NULL возвращает false.

Попробуйте это так:

AND Upper(b.institution_desc) LIKE '%' || Upper(COALESCE(:institution_desc,b.institution_desc,'')) || '%'
...