Преобразование текста в Datetime в определенном формате - PullRequest
0 голосов
/ 28 марта 2012

Мне нужно выражение, которое преобразует текстовый столбец (VARCHAR) в DATETIME, если и только если оно соответствует dd/MM/yyyy, d/MM/yyyy, dd/M/yyyy или d/M/yyyy.Если он не совпадает, то я хочу NULL.

У меня есть это ...

CASE ISDATE([DateField]) 
  WHEN 1 THEN CONVERT(DATETIME,[DateField],103) 
  ELSE NULL 
END

Однако это не удается, например, для '15/04/76' - с "Преобразованием не удалось"при преобразовании даты и времени из символьной строки "ошибка - тогда как я хотел бы, чтобы он возвращал NULL

Пример вывода

'1/6/1976'     -> 1976-06-01
'01/06/1976'   -> 1976-06-01
'13/06/2001'   -> 2001-06-13
'06/13/2001'   -> NULL
'13/06/76'     -> NULL

Есть ли способ заставить ISDATE проверить данный формат?

Документация , кажется, предлагает так ...

ISDATE является детерминированным, только если используется с функцией CONVERT, задан параметр стиля CONVERT и стильне равно 0, 100, 9 или 109.

Но ISDATE принимает только один аргумент, так как я могу "использовать его с функцией CONVERT", если я этого еще не делал?

Ответы [ 3 ]

1 голос
/ 28 марта 2012

Ну, во-первых, с какой стати вы храните значения даты и времени в столбце varchar?Это основной грех по ряду причин, не в последнюю очередь из-за того, что вы не получаете никакой проверки того, что данные являются (или могут быть преобразованы) датой-временем.Вам также следует рассмотреть возможность проверки входных данных, даже если вы оставите столбец как varchar, чтобы у вас не было такого большого количества потенциальных форматов, которые вы хотели бы считать допустимыми.немного от @G Mastros:

DECLARE @f TABLE(i INT, d VARCHAR(32));

INSERT @f VALUES
(1,'15/04/76'),
(2,'15/04/1976'),
(3,'1/3/1976'),
(4,'1/3/76'),
(5,'15/3/1976'),
(6,'22/22/22'),
(7,'Yesterday');

SET DATEFORMAT DMY;

SELECT i, d, d2 = CASE WHEN ISDATE(d) = 1
    AND d LIKE '%/[0-9][0-9][0-9][0-9]'
    THEN CONVERT(DATETIME, d, 103) END
  FROM @f;

Результаты:

i  d           d2
-  ----------  -----------------------
1  15/04/76    NULL
2  15/04/1976  1976-04-15 00:00:00.000
3  1/3/1976    1976-03-01 00:00:00.000
4  1/3/76      NULL
5  15/3/1976   1976-03-15 00:00:00.000
6  22/22/22    NULL
7  Yesterday   NULL

PS Это будет отличный случай для TRY_CONVERT в SQL Server 2012. Этоделает именно то, что вы спрашиваете - он пытается преобразовать в указанный тип данных;если не может, возвращается NULL.

1 голос
/ 28 марта 2012

Здесь вы можете сделать вложенный оператор case.Первый может проверить, есть ли у вас строка из 10 символов 2 для дня, 2 для месяца, 4 для года и 2 для разделителей = 10 символов.

SET DATEFORMAT DMY;

    Case When DateField Like '%/%/[0-9][0-9][0-9][0-9]' 
         Then Case When IsDate(DateField) = 1 
                   Then CONVERT(DATETIME,[DateField],103) 
                   End
         End

Исправлено: я изменил код для использованиянапример поиск, при котором в конце строки указывается знак / ГГГГ, а затем выполняется проверка IsDate, позволяющая выделить один день и / или месяц.

0 голосов
/ 28 марта 2012

Спасибо за ответы, ребята.

Я сделал это так ...

CASE ISDATE([DateField]) WHEN 1 THEN 
    CASE WHEN SUBSTRING([DateField],LEN([DateField])-4,1) = '/' THEN
        CASE WHEN CHARINDEX('/',[DateField],LEN([DateField])-3)=0 THEN
            CONVERT(datetime, [DateField] , 103) 
        END
    END
END

, что довольно неприятно, поэтому все равно оценил бы что-нибудь более аккуратное!

Но это тоже не работает - все равно ошибки в датах формата мм / дд / гггг!

Удалите этот последний комментарий - кажется, он работает сейчас? Вероятно, что-то делать с SET DATEFORMAT

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