Преобразование нескольких форматов даты в значение DateTime в SQL Server - PullRequest
3 голосов
/ 10 декабря 2011

Я пишу сценарий SQL для переноса данных из старой таблицы в новую и в процессе, чтобы внести некоторую строгость в данные, используя надлежащие типы данных.

В старой таблице есть поле varchar, которое содержит даты в различных форматах. На данный момент я обнаружил как минимум 6 форматов для дат в этом поле:

dd/mm/yyyy
dd/mm/yy
dd.mm.yy
dd-mm-yyyy
ddxx mmmm yyyy
dd.m.yy

Я хочу преобразовать все эти даты в правильные значения даты и времени.

Пост здесь о функции CONVERT очень полезен.

Однако мне интересно, как можно определить , какой из вышеперечисленных форматов применяется для каждой обрабатываемой строки.

Один из вариантов - выполнить CONVERT для каждого возможного формата в блоке TRY / CATCH и просто использовать тот, который не сбоит.

Единственным другим вариантом может быть манипулирование строками для определения формата, но это может быть очень сложно написать самому. Если бы это был единственный вариант, я бы, вероятно, отказался от SQL и записал бы миграцию как приложение на C # (только тогда для его запуска потребовалось бы гораздо больше времени, чем для собственного сценария SQL).

Кто-нибудь знает более простой способ сделать это в SQL Server?

1 Ответ

2 голосов
/ 11 декабря 2011

Мое решение проблемы до сих пор состоит в том, чтобы использовать вложенные блоки try / catch для попытки конвертации при каждом потенциальном формате даты.

В противном случае, для необычных форматов даты, таких как «12 августа 2011»Я прибег к ручному разбору строк (что оказалось проще, чем я ожидал).

Вот код, который я использую, но для чьих-то особых нужд его необходимо будет соответствующим образом адаптировать.(Предполагается, что табличной переменной '@datetable' заполнено поле [DOB] из базы данных.)

DECLARE @dateTable TABLE
(
    [DOB] varchar(max),
    [DOBReal] datetime,
    [DOBFilled] bit
)

DECLARE @id INT

WHILE (SELECT COUNT(*) FROM @dateTable Where [DOBFilled] = 0) > 0
BEGIN
    SELECT TOP 1 @Id = ID From @dateTable Where [DOBFilled] = 0

    DECLARE @sourceString VARCHAR(100) = 
        (SELECT TOP 1 [DOB] 
        FROM @dateTable
        WHERE ID = @Id)

    DECLARE @result DATETIME = NULL

    BEGIN TRY
        SET @result = CONVERT(DATETIME, @sourceString, 3)
    END TRY
    BEGIN CATCH
        BEGIN TRY
            SET @result = CONVERT(DATETIME, @sourceString, 103)
        END TRY
        BEGIN CATCH
            BEGIN TRY
                SET @result = CONVERT(DATETIME, @sourceString, 4)
            END TRY
            BEGIN CATCH
                BEGIN TRY
                    SET @result = CONVERT(DATETIME, @sourceString, 104)
                END TRY
                BEGIN CATCH
                    BEGIN TRY
                        SET @result = CONVERT(DATETIME, @sourceString, 5)
                    END TRY
                    BEGIN CATCH
                        BEGIN TRY
                            SET @result = CONVERT(DATETIME, @sourceString, 105)
                        END TRY
                        BEGIN CATCH
                            BEGIN TRY
                                SET @result = CONVERT(DATETIME, @sourceString, 6)
                            END TRY
                            BEGIN CATCH
                                BEGIN TRY
                                    SET @result = CONVERT(DATETIME, @sourceString, 106)
                                END TRY
                                BEGIN CATCH
                                    IF (SUBSTRING(@sourceString, 3, 1) = ' ' 
                                        AND SUBSTRING(@sourceString, 6, 1) = ' ')
                                    BEGIN
                                        IF (LEN(@sourceString) = 8)
                                        BEGIN
                                            SET @result = 
                                                CONVERT(
                                                    DATETIME, 
                                                    (SUBSTRING(@sourceString, 1, 2) + '/' + 
                                                    SUBSTRING(@sourceString, 4, 2) + '/' +
                                                    SUBSTRING(@sourceString, 7, 2)),
                                                    3)
                                        END
                                        ELSE
                                        IF (LEN(@sourceString) = 10)
                                        BEGIN
                                            SET @result = 
                                                CONVERT(
                                                    DATETIME, 
                                                    (SUBSTRING(@sourceString, 1, 2) + '/' + 
                                                    SUBSTRING(@sourceString, 4, 2) + '/' +
                                                    SUBSTRING(@sourceString, 7, 4)),
                                                    103)
                                        END
                                    END
                                    ELSE 
                                    IF (LEN(@sourceString) >= 11 
                                        AND ISNUMERIC(SUBSTRING(@sourceString, 1, 1)) = 1)
                                    BEGIN
                                        DECLARE @date VARCHAR(100) = SUBSTRING(@sourceString, 1, 1)

                                        IF (ISNUMERIC(SUBSTRING(@sourceString, 2, 1)) = 1)
                                        BEGIN
                                            SET @date = SUBSTRING(@sourceString, 1, 2)
                                        END

                                        SET @date = 
                                            @date + '/' +
                                            CASE 
                                                WHEN CHARINDEX('January', @sourceString) > 0 THEN '01'
                                                WHEN CHARINDEX('February', @sourceString) > 0 THEN '02'
                                                WHEN CHARINDEX('March', @sourceString) > 0 THEN '03'
                                                WHEN CHARINDEX('April', @sourceString) > 0 THEN '04'
                                                WHEN CHARINDEX('May', @sourceString) > 0 THEN '05'
                                                WHEN CHARINDEX('June', @sourceString) > 0 THEN '06'
                                                WHEN CHARINDEX('July', @sourceString) > 0 THEN '07'
                                                WHEN CHARINDEX('August', @sourceString) > 0 THEN '08'
                                                WHEN CHARINDEX('September', @sourceString) > 0 THEN '09'
                                                WHEN CHARINDEX('October', @sourceString) > 0 THEN '10'
                                                WHEN CHARINDEX('November', @sourceString) > 0 THEN '11'
                                                WHEN CHARINDEX('December', @sourceString) > 0 THEN '12'
                                            END

                                        IF (ISNUMERIC(RIGHT(@sourceString, 4)) = 1)
                                        BEGIN
                                            SET @date = @date + '/' + RIGHT(@sourceString, 4)
                                        END

                                        BEGIN TRY
                                            SET @result = CONVERT(DATETIME, @date, 103)
                                        END TRY
                                        BEGIN CATCH

                                        END CATCH
                                    END
                                END CATCH
                            END CATCH
                        END CATCH
                    END CATCH
                END CATCH
            END CATCH
        END CATCH
    END CATCH

    UPDATE @dateTable 
    SET [DOBReal] = @result, [DOBFilled] = 1
    WHERE [ID] = @Id

END

SELECT * FROM @dateTable

Опять же, если кто-нибудь знает о лучшем решении или какой-либо встроенной функции SQL Serverчто может справиться с этим более элегантно, я все уши.

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