#sql #sql-server #sql-server-2016 #sp-executesql
#sql #sql-сервер #sql-server-2016 #sp-executesql
Вопрос:
Я использую EXEC sp_executesql для динамического запроса в SQL Server 2016 и натыкаюсь на то, когда пользователь хочет пройти через год. У меня есть поле datetime с именем tkemdate, и оно хранится как поле datetime в SQL.
Хотя SQL сохраняет его как datetime, пользователь передает только параметр year (2020, 2019, 2018 и т. Д.). Как мне заставить запрос принять только год?
Вот моя хранимая процедура с параметром datetime.
(
@tkemdate datetime
)
AS
BEGIN
Declare @SQL NVARCHAR(MAX)
Set @SQL = 'SELECT timekeep.tkinit, timekeep.tkfirst, timekeep.tklast,
year(timekeep.tkemdate) as tkemdate
FROM abc123.timekeep'
WHERE 1 = 1
IF @tkemdate IS NOT NULL
Select @SQL = @SQL 'AND ([tkemdate] = @tkemdate)'
EXEC sp_executesql @SQL, N'@tkemdate datetime', @tkemdate
END
Комментарии:
1. Почему входной partameter (
@tkemdate
) объявлен какdatetime
?2. Этот SQL не завершен, но, похоже, это хранимая процедура / функция определения. Следовательно, вызов
sp_executesql
не является «проблемой», это определение SP / функции;@tkemdate
должно быть определено какint
if, что является входным параметром. В противном случае вам нужно сообщить пользователю, что2019
это недопустимоеdatetime
значение, и что они должны использовать что-то вроде'20190101'
.
Ответ №1:
Вы можете использовать что-то вроде этого:
IF @year IS NOT NULL
Select @SQL = @SQL ' AND (YEAR([tkemdate]) = @year)'
EXEC sp_executesql @SQL, N'@year int', @year=@year;
Непонятно, откуда @year
берется, но вы говорите, что пользователь проходит в год.
Если вы хотите использовать только год с @tkemdate
этого момента:
IF @tkemdate IS NOT NULL
Select @SQL = @SQL ' AND (YEAR([tkemdate]) = YEAR(@tkemdate))';
EXEC sp_executesql @SQL, N'@@tkemdate datetime', @@tkemdate=@@tkemdate;
Ответ №2:
Это может быть и что-то подобное — где ваша процедура имеет целочисленный параметр, представляющий год.
Мы также могли бы добавить к нему некоторую проверку, например, если @year меньше 1000 или больше 2500.
CREATE PROCEDURE abc123.get_timekeep_records (
@year int
)
AS
BEGIN
SET NOCOUNT ON; -- I usually add this because of a PHP driver
DECLARE @SQL NVARCHAR(MAX)
SET @SQL = 'SELECT timekeep.tkinit, timekeep.tkfirst, timekeep.tklast,
YEAR(timekeep.tkemdate) as [tkemdate]
FROM abc123.timekeep
WHERE 1 = 1 '
-- Validation
IF @year < 1000 OR @year > 2500
RAISERROR('Invalid year: %i', 16, 1, @year)
IF @year IS NOT NULL
SELECT @SQL = @SQL 'AND (YEAR(timekeep.tkemdate) = @year)'
EXEC sp_executesql @SQL, N'@year int', @year;
END