Как проверить, включает ли DateTime время в SQL Server - PullRequest
2 голосов
/ 14 марта 2019

У меня есть хранимая процедура, которая принимает параметр datetime.Мне нужно определить, включает ли данный параметр datetime время.

Теперь, DATEPART(hour, @datetimeValue) = 0 не работает в моем случае, потому что дата и время могут быть предоставлены как 3/14/2019 0:00, что относится к 12:00 идопустимо.

Вернуть true, если ввод:

'3/14/2019 0:00'
'3/14/2019 15:00'

Возвращать false, только если ввод не имеет времени:

'3/14/2019'

Спасибо всем за их ввод.Похоже, что нет другого решения, кроме изменения параметра хранимой процедуры на varchar.

Ответы [ 7 ]

2 голосов
/ 14 марта 2019

Технически невозможно обработать требование в хранимой процедуре.

Параметр DateTime в вашей хранимой процедуре всегда будет содержать аспект времени, который либо явно передан ей , либо * 1005.* по умолчанию используется полночь прошедшей даты.Невозможно узнать, был ли вызывающий явно передан во временном аспекте или нет.

У вас есть 2 варианта:

  1. Измените тип входящих данных параметра на varcharи пусть хранимая процедура проанализирует это в DateTime и обработает проверку.
  2. Сделайте так, чтобы вызывающий обработчик обрабатывал любую проверку, связанную со временем, и удалите это требование из вашего кода.
1 голос
/ 14 марта 2019

Это грубо, но оно делает то, что вам нужно.Если его отбросить, например, часть какого-либо импорта, он может быть достаточно хорош для ваших нужд.

Я уверен, что этот подход может быть улучшен с более глубоким пониманием того, как получать детали текущего выполнения SQL изнутриPROC, я быстро взглянул на использование query plans и т. д.

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

ALTER PROCEDURE Hastime(@d AS DATETIME) 
AS 
  BEGIN

      -- Is there a easier way to get from DBCC INPUTBUFFER to a SQL variable? 
      CREATE TABLE #temp 
        ( 
           spid       INT, 
           eventtype  NVARCHAR(30), 
           parameters INT, 
           eventinfo  NVARCHAR(4000) 
        )     
      INSERT INTO #temp 
                  (eventtype, 
                   parameters, 
                   eventinfo) 

      EXEC ('DBCC INPUTBUFFER(' + @@spid +') WITH NO_INFOMSGS') 

      -- Yes, we could do this better
      IF EXISTS (SELECT * 
                 FROM   #temp 
                 WHERE  eventinfo LIKE '%:%') 
        SELECT 'Time' 
      ELSE 
        SELECT 'No Time' 
  END     
go     
EXEC dbo.Hastime 
  '2000/06/01' 

go     
EXEC dbo.Hastime 
  '2000/06/01 00:00:00' 
1 голос
/ 14 марта 2019

По умолчанию DATETIME включает время, установленное на полночь (например, «00: 00: 00»), даже если вы не используете часть времени. Если ваши datetime являются строками, то вот способ узнать, является ли время частью строки (хотя это немного хакерски):

SELECT CASE WHEN CHARINDEX(':', '3/14/2019 0:00') > 0 THEN 1 ELSE 0 END   -- Returns 1
SELECT CASE WHEN CHARINDEX(':', '3/14/2019 15:00') > 0 THEN 1 ELSE 0 END  -- Returns 1
SELECT CASE WHEN CHARINDEX(':', '3/14/2019') > 0 THEN 1 ELSE 0 END        -- Returns 0

По сути, это просто поиск по строке и проверка на наличие двоеточия в строке. Это соответствует вашим критериям, хотя.

1 голос
/ 14 марта 2019

Единственное решение, о котором я могу подумать, это ALTER ваш SP и использование двух (2) параметров вместо этого, один - DATE, а второй - TIME тип данных как:

CREATE PROCEDURE HasTime(
    @MyDate DATE = NULL,
    @MyTime TIME = NULL
)
AS
BEGIN
    IF @MyTime IS NULL
        SELECT 'There is no time'
            ELSE
                SELECT 'There is time';
END;

EXEC dbo.HasTime '2019-01-01', NULL; --Or EXEC dbo.HasTime '2019-01-01';
EXEC dbo.HasTime '2019-01-01', '00:00:00';

Live Demo

0 голосов
/ 14 марта 2019

Единственный способ - передать тип varchar в процедуру вместо datetime в противном случае мы не можем сделать разницу между датой без времени и датой в полночь здесь вы можете проверить это ограничение Следующий скрипт иллюстрирует это ограничение:

declare @d as datetime
declare @d1 as datetime

set @d='01/01/2019'
set @d1='01/01/2019 00:00:00:00'

if @d=@d1 print 'equal' else print 'not equal'
0 голосов
/ 14 марта 2019

Я бы бросил как date:

select (case when convert(date, @datetimeValue) = @datetimeValue then 'NoTime'
             else 'HasTime'
        end)
0 голосов
/ 14 марта 2019

Вы можете сделать такую ​​проверку, но если время действительно полночь, оно вернет недопустимое время:

-- returns 'NOTime'
SELECT CASE WHEN CAST('1/1/2019' AS TIME) = '00:00:00.000' THEN 'NOTime' ELSE 'TIME' END

-- returns 'TIME'
SELECT CASE WHEN CAST(GetDate() AS TIME) = '00:00:00.000' THEN 'NOTime' ELSE 'TIME' END
...