EXEC sp_executesql с параметром datetime?

#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