2015-05-07 2 views
0

У меня есть следующий динамический SQL-запрос, который я использую для фильтрации результатов для диапазона данных. Если мои «createdFrom» и «createdTo» даты не являются нулевыми, я добавляю предложение where в мой оператор select.TSQL - см., Если дата падает между датой

У меня 2 вопроса:

  1. Как бы вы об этом? Правильно ли моя логика?

  2. В настоящее время я получаю сообщение об ошибке, когда я добавить код, приведенный ниже, почему бы мне получать это ?:

    Конверсия удалось при преобразовании строки символов в smalldatetime тип данных.

Declare @createdFromDate SMALLDATETIME = NULL , 
     @createdToDate SMALLDATETIME = NULL 

IF @createdFromDate IS NOT NULL 
    BEGIN 
     SELECT @sWhere = @sWhere + 'AND g.CreatedOn > '[email protected] 
    END 
IF @createdToDate IS NOT NULL 
    BEGIN 
     SELECT @sWhere = @sWhere + ' AND g.CreatedOn <'[email protected] 
    END 
+1

Какую версию SQL Server вы используете? – Stephan

+1

SQL Server 2012 – Mark

+1

Следует избегать динамического SQL из-за их уязвимости к атакам SQL Injections. В этом невозможно, а затем попробуйте преобразовать smallDateTime в данные char, прежде чем конкатенировать их в @sWhere. –

ответ

2

Что вызывает ваш вопрос вы пытаетесь объединить в smalldatetime с, так строковые типы данных, такие как VARCHAR. Вы можете просто указать свои даты как VARCHAR, чтобы обойти это. CONCAT() было бы даже лучше. Это ваш лучший друг при конкатенации значений разных типов данных. Я настоятельно рекомендую использовать его, к сожалению, это только поддержка SQL Server 2012+ и выше, и мало кто знает, что он даже существует.

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

Declare @createdFromDate SMALLDATETIME = NULL, 
     @createdToDate SMALLDATETIME = NULL 

SELECT * 
FROM yourTable 
WHERE (
      date_column > @createdFromDate 
      OR @createdFromDate IS NULL 
     ) 
     AND 
     (
      date_column < @createdToDate 
      OR @createdToDate IS NULL 
     ) 
2

Для вашего вопроса

В настоящее время я получаю сообщение об ошибке, когда я добавить код, приведенный ниже, почему бы я получаю это?

Причина вы получаете эту ошибку, когда запрос выполняется ваше состояние становится

AND g.CreatedOn > 2015-05-07 

Что является недопустимым, но вместо того, чтобы ваша потребность

AND g.CreatedOn > '2015-05-07' 

Следовательно, ваш SQL должен быть

SELECT @sWhere = @sWhere + 'AND g.CreatedOn > '''[email protected] + '''' 

За ваш вопрос

Как бы вы это сделали? Правильно ли моя логика?

Вы должны использовать sp_executesql и передать переменную в динамическом SQL как это.

IF @createdFromDate IS NOT NULL 
    BEGIN 
     SELECT @sWhere = @sWhere + 'AND g.CreatedOn > @createdFromDate' 
    END 

IF @createdToDate IS NOT NULL 
    BEGIN 
     SELECT @sWhere = @sWhere + ' AND g.CreatedOn < @createdToDate' 
    END 

Вместо

EXEC(@SQL) 

Вы бы использовать

EXEC sp_executeSQL @SQL,N'@createdFromDate smalldatetime,@createdToDate smalldatetime',@createdFromDate,@createdToDate 

Где @SQL построены из вашего @Where

Примечания: Вам не нужен динамический SQL, если это i s единственная причина для его использования.

2

Прямой ответ на ваш вопрос заключается в том, что константы даты должны быть заключены в одинарные кавычки.Вместо этого:

SELECT @sWhere = @sWhere + 'AND g.CreatedOn > '[email protected] 

Использование:

SELECT @sWhere = @sWhere + 'AND g.CreatedOn > ''' + @createdFromDate + '''' 

Правильный ответ на ваш вопрос в том, что вы должны использовать sp_executesql для выполнения динамического SQL. Это позволяет включать параметры, так что вы можете просто сказать:

exec sp_executesql @sql, 
    N'@createdFromDate date', 
    @createdFromDate = @createdFromDate; 

где @sql является строка, которая выглядит как:

select . . . 
. . . 
where . . . and 
     g.CreatedOn = @createdFromDate;