Почему IS NULL работает, а параметр SQL с DBNull.Value для DateTime - нет? - PullRequest
0 голосов
/ 03 октября 2018

У меня есть консольное приложение C #, которое выполняет поиск в базе данных на SQL Server 2014. Оно запрашивает таблицу со столбцом DateTime с именем EffectiveDate, который допускает пустые значения.

Если я пишу стандартный запрос SQL, который использует«ГДЕ EffectiveDate is NULL», результаты возвращаются правильно.Если я изменю предложение WHERE на принятие параметра и установлю для этого параметра значение DBNull.Value, результат будет нулевым.

Пример 1 Использование IS NULL -> resultObj имеет соответствующее значение:

    public void RetrieveFileType()
    {
        string sSQL = "SELECT [FileType]  " +
                      "FROM DTCC_APP_ProcessControl " +
                      "WHERE [EffectiveDate] IS NULL ";

        using (SqlConnection oConn = GetNewConnection())
        {
            using (SqlCommand cmd = new SqlCommand(sSQL, oConn))
            {
                object resultObj = cmd.ExecuteScalar();
            }
        }
    }

Пример 2 Использование DBNull.Value -> resultObj = null:

    public void RetrieveFileType()
    {
        string sSQL = "SELECT [FileType]  " +
                      "FROM DTCC_APP_ProcessControl " +
                      "WHERE [EffectiveDate] = @EffectiveDate";

        using (SqlConnection oConn = GetNewConnection())
        {
            using (SqlCommand cmd = new SqlCommand(sSQL, oConn))
            {
                cmd.Parameters.AddWithValue("@EffectiveDate", DBNull.Value);

                object resultObj = cmd.ExecuteScalar();
            }
        }
    }

Я также пытался:

cmd.Parameters.Add("@EffectiveDate", SqlDbType.DateTime).Value = DBNull.Value;

и

cmd.Parameters.AddWithValue("@EffectiveDate", SqlDateTime.Null);

Единственный раз, когда я получаюрезультат, если я использую IS NULL.Это упрощенный пример, я буду необязательно устанавливать значение или Нуль для @ EffectiveDate.

Я прочитал другую информацию в Интернете, и мне кажется, что все, что мне нужно, это столбец базы данных, обнуляемый нулем, и использовать DBNull.Value дляпараметр и он должен работать.Чего мне не хватает?

Ответы [ 2 ]

0 голосов
/ 03 октября 2018

Проблема не связана с параметризацией, но с тем фактом, что параметр может иметь значение NULL.Как то, что Стив сказал, прежде чем вы не сможете сравнить NULL с NULL напрямую, иначе он ничего не вернет (он всегда оценивается как ложный в соответствии со стандартом SQL).

Прямое сравнение в вашем примере 2 хорошо работает, когда параметр гарантированно никогда не будет NULL, пример 1 подойдет, если он всегда будет NULL.Однако, если есть вероятность того, что он будет NULL или нет в соответствии с каким-либо внешним условием, мы должны учитывать это и в запросе SQL.Что-то вроде этого будет делать:

SELECT [FileType]
FROM DTCC_APP_ProcessControl
WHERE [EffectiveDate] = @EffectiveDate OR @EffectiveDate IS NULL

Это учитывает обе ситуации, однако, обратите внимание, что это выражение не является SARGable и не будет использовать индекс для столбцов EffectiveDate, если он есть.

Альтернативный подход заключается в том, чтобы, в зависимости от конечного значения параметра, клиент решал отправить тот или иной запрос, выбирая между примером 1 или 2 динамически.Это, вероятно, приведет к повышению производительности и использованию индекса.

0 голосов
/ 03 октября 2018

Потому что NULL в БД отличается от c #.

NULL = NULL возвращает false в Sql.Вы должны использовать IS NULL для сравнения

...