Работа с datetime с динамическим запросом в SQL Server - PullRequest
7 голосов
/ 17 февраля 2011

Эй, ребята, я использую динамический запрос, в котором я хочу использовать переменную, которая содержит дату и время, всякий раз, когда я выполняю запрос, который говорит, что не может преобразовать дату и время из строки, когда я преобразую эту переменную в varchar(max), она принимает его.как строка, а не datetime, так как я должен выполнить запрос ..

Ниже приведен мой запрос SQL, который я пытаюсь выполнить.

SET @SQL1 = 'SELECT B.FacId, B.FacName, B.BookCode, B.BookName, B.Quantity, 
CONVERT(VARCHAR(10), B.TillDate, 104) AS TILLDATE FROM '+@TABLE+' B
WHERE B.TillDate BETWEEN CONVERT(VARCHAR(10),'+@FROMDATE+', 101) and 
CONVERT(VARCHAR(10), DATEADD(DD,1,'+@TODATE+'), 101)'

EXEC SP_EXECUTESQL @SQL1

здесь @fromdate и @todate - это тип datetime, полученный из другой временной таблицы.и хранится в этих переменных ..

Теперь, как я должен выполнить этот запрос .. Любые предложения.пожалуйста, ответьте в ближайшее время ...

спасибо и привет abbas electricwala.

Ответы [ 7 ]

24 голосов
/ 17 февраля 2011

Вы должны указать свои даты ..

SET @SQL1 = 
   'SELECT B.FacId, 
           B.FacName, 
           B.BookCode, 
           B.BookName, 
           B.Quantity, 
           CONVERT(VARCHAR(10), B.TillDate, 104) AS TILLDATE 
           FROM '+@TABLE+' B 
           WHERE B.TillDate BETWEEN ''' + CONVERT(VARCHAR(10),@FROMDATE, 101) + ''' and ''' + CONVERT(VARCHAR(10),DATEADD(DD,1,@TODATE), 101) + ''''
6 голосов
/ 18 февраля 2011

Вы не должны объединять свои значения параметров, как это. Лучшее решение - использовать параметризованный запрос с sp_executesql.

DECLARE @sql nvarchar(4000)

select @sql = N'
  SELECT B.FacId 
       , B.FacName
       , B.BookCode
       , B.BookName
       , B.Quantity
       , CONVERT(VARCHAR(10), B.TillDate, 104) AS TILLDATE 
    FROM ' + quotename(@TABLE) + N' B
   WHERE B.TillDate BETWEEN cast(floor(cast(@fromDate as float)) as datetime)
                        AND cast(floor(cast(@toDate as float)) as datetime)'

EXEC sp_executesql @sql, N'@fromDate datetime, @toDate datetime', @FROMDATE, @TODATE

Обратите внимание на sp_executesql:

  • Параметры NVARCHAR значения
  • 3-й и 4-й параметры сохраняют свой первоначальный тип данных и не нуждаются в преобразовании в varchar. Это снова защищает от SQL-инъекций и делает запрос более читабельным, поскольку вы предотвращаете использование супа кавычек, который так часто встречается в Dynamic SQL

Некоторые дополнительные изменения были внесены в запрос:

  • Имя таблицы заключено в функцию QUOTENAME(), которая защищает от SQL-инъекций в имя объекта
  • Способ удаления части даты из переменных даты и времени не очень оптимален. Выполнение convert(,,101) является дорогостоящей операцией, которую лучше выполнить, используя приведение к плаванию и получение пола этого значения.
2 голосов
/ 17 февраля 2011

Я думаю, это может сработать:

 DECLARE @tempdate datetime
 SET tempdate =DATEADD(DD,1,@TODATE)
 SET @SQL1 = 'SELECT B.FacId, B.FacName, B.BookCode, B.BookName, B.Quantity,'''+  cast     (B.TillDate as VARCHAR(50))+''' AS TILLDATE FROM '+@TABLE+' B WHERE B.TillDate BETWEEN '''+cast(@FROMDATE as VARCHAR(50))+''' and  '''+cast(@tempdate as VARCHAR(50))'''

 EXEC SP_EXECUTESQL @SQL1 
2 голосов
/ 17 февраля 2011

Я бы хотел увидеть ваши определения переменных, но я подозреваю, что это потому, что @FROMDATE и @TODATE - это datetime, и вы используете их в выражении конкатенации строк. Таким образом, вы можете исправить это:

SET @SQL1 = 'SELECT B.FacId, B.FacName, B.BookCode, B.BookName, B.Quantity, CONVERT(VARCHAR(10), B.TillDate, 104) AS TILLDATE FROM '+@TABLE+' B WHERE B.TillDate BETWEEN CONVERT(VARCHAR(10),'+CAST(@FROMDATE as varchar(15))+', 101) and CONVERT(VARCHAR(10), DATEADD(DD,1,'+CAST(@TODATE as varchar(15))+'), 101)'

Однако лучшие решения:

  1. Ни в коем случае не используйте динамический SQL, возможно, @TABLE не сильно отличается, и вы можете объединить их в представление или что-то в этом роде
  2. Передача параметров непосредственно в sp_executeSQL и, таким образом, сохранение их типов, например,

SET @SQL1 = 'SELECT B.FacId, B.FacName, B.BookCode, B.BookName, B.Quantity, B.TillDate AS TILLDATE FROM '+@TABLE+' B WHERE B.TillDate BETWEEN @inFROMDATE and @inTODATE'

EXEC SP_EXECUTESQL @SQL1,'@inFROMDATE datetime, @inTODATE',@inFromDate = @FROMDATE, @inTODATE = @TODate

0 голосов
/ 27 сентября 2018

Запустите этот пример и адаптируйте его под свой код. (Нет 3 смежных одинарных кавычек)

Declare @FromDATE  datetime
;Declare @ToDATE datetime
;set @FromDATE = getdate() 
;set @ToDATE = @FromDATE 

;Print 'WHERE TillDate BETWEEN ' + char(39) + CONVERT(VARCHAR(10),@FromDATE, 101) 
+ char(39) + ' and ' + char(39) + CONVERT(VARCHAR(10),@ToDATE, 101) + char(39)
0 голосов
/ 08 мая 2013

Уже поздно, но, может быть, это кому-нибудь поможет

Вам нужны цитаты вокруг даты, вы уже получили свой ответ.

Ниже приведен пример того, что я обычно ставлюв моем запросе

'(CONVERT(DATETIME,CONVERT(varchar,gd.CreatedDate),106) <= CONVERT(DATETIME,'''+CONVERT(varchar, @EndDate ) +''',106))'

обратите внимание, что @EndDate имеет тип Datetime здесь

0 голосов
/ 17 февраля 2011

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

declare @sql1 varchar(max)
declare @table sysname
declare @FROMDATE datetime
declare @TODATE datetime

set @table = 'MyTable'
set @FROMDATE = GETDATE()
set @ToDATE = GETDATE()


SET @SQL1 = 'SELECT B.FacId, B.FacName, B.BookCode, B.BookName, B.Quantity, 
CONVERT(VARCHAR(10), B.TillDate, 104) AS TILLDATE FROM '+@TABLE+' B
WHERE B.TillDate BETWEEN CONVERT(Datetime,''' + CONVERT(VARCHAR(10),@FROMDATE, 101) 
+ ''', 101) and CONVERT(DATETIME,'''+ CONVERT(VARCHAR(10), DATEADD(DD,1,@TODATE), 101) + ''', 101)'


print @sql1

Но посмотрите на ответ Джоэла Мэнсфорда, чтобы избежать двойного преобразования.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...