1. SQL / Говнокод #2147

    −858.3

    1. 1
    Функция nullif( a, b ) возвращает null если a=b, иначе а.

    Всем отделом думали зачем это нужно. С трудом высосали пример из пальца. Видимо какой-то индус решил написать функцию века.

    Запостил: dim1r, 16 Ноября 2009

    Комментарии (25) RSS

    • это функция обратная coalesce
      например, если надо вместо null вернуть 0, то это ведь нормально: coalesce(x, 0)
      а если в обратную сторону, то nullif(x, 0)
      Ответить
      • нифика
        coalesce(a,b) =
        case
        when a is not null then a
        when b is not null then b
        else null
        end;

        nullif(a,b)=
        case
        when a=b then null e
        else a
        end;
        Ответить
    • Тьфу, и что здесь говнокодерского? В некоторых случаях очень даже изящно получается.
      Ответить
      • Ну давай свой изящный случай показывай...
        Ответить
    • да, действительно, зачем нужна?

      Я вот что заметил: делаешь left join например:

      select t1.id, t2.id from t1 left join t2 on (t1.id = t2.id);

      так вот у тебя в столбце t2.id будет то значение какое в столбце t1.id, тo null.

      Применение функции nullif: (nullif(t1.id, t2.id)), даст значение t1.id, где null в t2.id,
      и null в где в t2.id не null,

      короче null будет там где есть совпадение, иначе будет данные из первой таблицы.

      И это можно использовать для получения тех id таблицы t1, которых нет в t2,
      (да, это можно сделать с помощью case, но nullif короче)

      То есть мы получаем id из таблицы t1, которых нет в t2, при этом не ограничивая выборку.
      Ответить
      • select * from t1 where id NOT in(select id from t2)
        это тоже самое ?
        Ответить
        • Ты ограничил выборку, в моём случае ты получаешь id-шники, без ограничения других строк.
          Ответить
          • а оно надо ?
            Ответить
            • Если тебе нужны другие строки, то надо.
              Ответить
              • Когда начинается экзотика в желаниях, то возникает дремучий и запутанный код. И nullif() тут не спасёт, скорее всего.
                Ответить
    • Автору поста позор и порицание. И _нЕфиГа_ огрызаться на резонное замечание.
      Ответить
      • о сколько нам открытий чудных готовит говнокода друг!
        и кодер - сын ошибок трудных
        и аналитик - парадоксов друг
        Ответить
    • Нормальная функция. У нас на работе, например, в проекте используется повсеместно в конструкциях вида
      ...
      where _переменная_ is null
      Препроцессор заменит _переменная_ на вычисляемое значение, если переменная пуста, получим
      where null is null
      что идиотия ещё та.

      Посему, есть защищающая конструкция вида:
      where nullif_integer(_переменная_) is null
      которая развернётся в
      where nullif(-1, -1) is null
      И это будет вполне себе легальным кодом. Вывод - нехер гнать, если не понимаешь.
      Ответить
      • {Препроцессор заменит}
        Я извиняюсь, не понял что за предпроцессор.... У вас свой собственный ? Где вы его держите ?

        {Посему, есть защищающая}
        чтот не понял кого и от кого она защищает

        {where nullif_integer(_переменная_) is null}
        nullif_integer - гугле не знает такого слова

        {where nullif(-1, -1) is null
        И это будет вполне себе легальным кодом. }

        Чем он легальнее конструкции A is null, которая хоть иногда, да и выдаёт разные результаты, в то время как nullif(-1, -1) is null выдает всегда одно и тоже ?


        {Вывод - нехер гнать, если не понимаешь.}
        Вывод, Вы такой большой специалист, разбираетесь кто гонит, а кто нет,.. А вот не понимаете что A is null - самая что ни на есть легальньнейшая конструкция.
        Ответить
        • [Да, я тот самый гвест.]
          Собственный. Держим в сарае, боимся, чтоб не сбежал. -- простите, не сдержался
          Код SQL сначала прогоняется через фирменный препроцессор. Препроцессор вычисляет значения "внешних" переменных (т.е. они не нативные для SQL); кроме того, введённые пользователем данные тоже являются переменными.
          Функция защищает от попадания null-ов туда, куда им не надо.
          nullif_integer - реализация функции препроцессора, корпоративная тайна, название изменено. Естественно, нигде ничего и нет.

          Возможно, я не умею ничего объяснять, поэтому, сейчас поиграем в К.О.
          Предположим, у нас есть переменная $A, куда пользователь может ввести значение, например, сумму платежа. Предположим, у нас есть код, который засунет значение в таблицу, если оно не null.
          insert into payments(id, value)
          select nextval for PAYMENTS, $A
          where $A is not null
          Это код для препроцессора. Препроцессор вычисляет значение $A и отдаёт транслятору SQL. Если переменную явно не защитить конструкцией препроцессора, то он недолго думая соорудит вот такое:
          insert into payments(id, value)
          select nextval for PAYMENTS, null
          where null is not null
          И за это будет подвергнут анальной каре от транслятора, потому что null is not null - некошерно никоим образом. Пользуясь обёрткой, получим что-то вида:
          ...
          where nullif_integer($A) is not null
          Препроцессор не дурак, сверит переменную с null-ом и обнаружит, что таки да - пусто. Поскольку логика работы запроса препроцессору неизвестна, он не может отключать или подавлять строки. Также он не сможет оценить то, что в этом случае запрос не выполнится. Вместо этого он вместо реального значения переменной подставляет nullif.
          ...
          where nullif(-1, -1) is not null
          Транслятор вычислит nullif от двух аргументов (это null, как ни странно), сравнит 'null is not null' и не вывалится ничего.
          Пожалуйста, риальне рабочий пример, зачем это может быть надо и как это использовать. Т.е. для получения гарантированного null-a, который ну низя подставлять.
          Ответить
          • В общем, мудрёно.....

            Я так понял, что nullif() хорош, что бы в эмулировать null во внешней программе, где язык программирования не содержит null. В программе считаем, что A=-1 - это null. Тогда в sql надо делать обертку "nullif(:A, -1) is null".

            В общем null и так жизнь усложняет для sql программиов. Теперь есть возможность усложнить жизнь для других языков.
            Ответить
    • select f1/nullif(f2, 0)
      from table1

      Так можно защититься от деления на ноль...
      Ответить
    • Второе применение - нам нужно проссумировать несколько полей которые могут быть NULL

      SELECT i.*,
      nullif(
      nvl(a, 0) + nvl(b, 0) + nvl(c, 0),
      decode(a, NULL, 0) + decode(b, NULL, 0) + decode(c, NULL, 0)
      ) r
      FROM
      (
      SELECT 1 a, 2 b, 3 c FROM dual UNION ALL
      SELECT NULL a, 2 b, 3 c FROM dual UNION ALL
      SELECT NULL a, NULL b, 0 c FROM dual UNION ALL
      SELECT NULL a, NULL b, NULL c FROM dual
      ) i

      A B C R
      ---------- ---------- ---------- ----------
      1 2 3 6
      2 3 5

      0 0

      Короче, автору поста - "нереспект и неуважуха паполной"
      Ответить
      • и его отделу тоже
        Ответить
      • Сам ты не поэт
        ...
        NVL2( COALESCE(A,B,C), nvl(a, 0) + nvl(b, 0) + nvl(c, 0) , NULL ) R
        ...
        Ответить
    • Функция нихера не говнокод. Например, без нее такая конструкция не вернет корень дерева, если t1.id = t1.self_id.
      SELECT ...
      START WITH t1.id = p_id
      CONNECT BY PRIOR DECODE(t1.id, t1.self_id, NULL, t1.id) = t1.id
      Ответить
      • обычно корень такой
        select * from tree where parent_id is null

        Причем там в твоем примере nullif() ?

        Сначала всем отделом думали зачем этот nullif(), а теперь всеми участниками говнокода мозги ерошим. Единственный нормальное применение 1/nullif(a,0) см выше. Все остальное - от лукавого и криворукого.
        Ответить
      • В целом не спорю, но в данном случае CONNECT BY NOCYCLE PRIOR t1.self_id = t1.id вполне подойдет.
        Ответить
    • Вот еще крендель с задворок мега-интелекта
      LNNVL(А)

      LNNVL(true) false
      LNNVL(false) true
      LNNVL(NULL=1) true
      Ответить

    Добавить комментарий