Я заметил несколько проблем в коде, который вы разместили:
Вы объявляете @Sql
как varchar(max)
, но перед установкой его значения вы используете префикс N
. Это необходимо только при работе с данными Unicode (nchar
, nvarcar
). Это очень важно, но вы должны знать об этом.
Вы используете convert
без указания параметра style
. Это не так плохо при преобразовании целых чисел в строки, но это может вызвать неожиданное поведение при работе с датами. Всякий раз, когда вам нужно использовать строковое представление для значений даты / даты и времени, вы всегда должны использовать стандарт ISO8601, поскольку гарантируется, что сервер Sql всегда будет правильно преобразовывать его в дату, независимо от локальных настроек. Чтобы преобразовать значение datetime
в стандарт ISO8061, используйте стиль 126 в операторе convert
.
Вы используете varchar
без указания длины. Это плохая привычка, поскольку в SQL Server значения по умолчанию отличаются от длины в зависимости от контекста. Это 1 при объявлении переменной, но 30 при использовании в cast
и convert
.
Я внес некоторые изменения в ваш код, включая изменение char(2)
, которое вы использовали, на varchar(11)
(поскольку 11 символов будут содержать даже минимальное значение типа данных int, равное -2147483648) для @timeoffset
, и не было проблем с его отрицательным значением.
Вот мой тест:
DECLARE @timeOffset int = -10,
@start_date datetime = getdate(),
@sql nvarchar(max)
SET @sql =
N'SELECT '''+ convert(char(23), @start_date, 126) +''' As GetDate,
DATEADD(HOUR, '+ CAST(@timeOffset as varchar(11)) +', '''+ convert(char(23), @start_date, 126) +''') As DateAdd';
SELECT @Sql
EXEC(@sql)
Результаты:
SELECT '2018-11-08T20:33:31.670' As GetDate,
DATEADD(HOUR, -10, '2018-11-08T20:33:31.670') As DateAdd
GetDate DateAdd
2018-11-08T20:33:31.670 08.11.2018 10:33:3