Может ли функция NVL быть каскадной? - PullRequest
2 голосов
/ 10 июля 2009

можно ли каскадно использовать функцию nvl (...), об этом меня спросили в интервью IBM ..... и почему ????

Ответы [ 5 ]

14 голосов
/ 10 июля 2009

Еще лучше, используйте COALESCE

8 голосов
/ 30 ноября 2009

Мой ответ:

Да, NVL может быть каскадным. Это то, что я ожидал увидеть в коде, перенесенном из версий Oracle вплоть до 8i включительно, потому что COALESCE не поддерживался до Oracle 9i.

COALESCE - это стандарт ANSI SQL 99, и он работает как оператор CASE / SWITCH в том, как он оценивает каждое выражение по порядку и не продолжает вычислять выражения, если он встречает ненулевое выражение. Это называется коротким замыканием. Еще одно преимущество использования COALESCE заключается в том, что типы данных не должны совпадать, что требуется при использовании NVL.

Это:

SELECT COALESCE( 1.5 / NULL, 
                 SUM(NULL), 
                 TO_CHAR(SYSDATE, 'YYYY') ) abc
  FROM DUAL

... вернет: 2009 (в любом случае на следующие ~ 32 дня)

3 голосов
/ 10 июля 2009

Почему бы и нет? Например:

select NVL( null, NVL( null, 1 )) from dual 

Это может быть что-то вроде:

select NVL( delete_date, NVL( edit_date, create_date ))  AS last_change
from Table

Может быть, они хотели, чтобы вы сказали, что это детерминированная функция. Так что это реентерабельный.

1 голос
/ 02 мая 2012

Как уже говорили другие, NVL может быть каскадным, но предпочтительным решением будет вместо этого использовать COALESCE. Однако две функции не являются полностью взаимозаменяемыми:

1) как уже упоминалось, COALESCE оценивает аргументы только от первого до тех пор, пока не встретит аргумент, который не оценивается как ноль

2) однако COALESCE требует, чтобы все аргументы были одного и того же типа данных, поэтому STRICTER , чем NVL, который сначала попытается выполнить неявное преобразование.

1009 * Е.Г. *

SELECT COALESCE( 1.5 / NULL, 
             SUM(NULL), 
             TO_CHAR(SYSDATE, 'YYYY') ) abc
FROM DUAL

на самом деле выдает ошибку ORA-00932: inconsistent datatypes: expected NUMBER got CHAR

Вместо этого NVL вернет текущий год

SELECT NVL( 1.5 / NULL, 
             NVL( SUM(NULL), 
                 TO_CHAR(SYSDATE, 'YYYY') ) ) abc
FROM DUAL

Другие примеры:

select coalesce('some text',sysdate) from dual;

бросает ORA-00932: inconsistent datatypes: expected CHAR got DATE, а

select nvl('some text',sysdate) from dual;

возвращает some text, но

select nvl(sysdate,'some text') from dual;

бросает ORA-01841: (full) year must be between -4713 and +9999, and not be 0 (поскольку неявная попытка преобразования «некоторого текста» в дату не удалась)

1 голос
/ 01 декабря 2009

Наиболее распространенная причина, которую я видел для каскадных NVL, заключается в том, что базы данных меняются со временем. Первоначальный дизайн имел таблицу, которая позже была изменена, чтобы иметь больше столбцов в таблице. Операторы Alter создали новые столбцы с разрешением NULL, и это было использовано с учетом того, что Код сверху не нужно было менять. Проблема заключалась в том, что один столбец, change_date, был заменен несколькими столбцами. Update_Date, Comment_Date и Approval_date. Каждый из 3 новых столбца теперь объединены, чтобы получить "change_date" в представлении с

create or replace view OldTableNmae as
select other_columns
    , nvl ( update_date, nvl ( comment_date, approval_date ) ) change_date
    , more_columns
from  new_table
/
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...