Конференция "Базы" » T-SQL проверка на коректную дату в европейском формате в строке [MSSQL]
 
  • lastzealot © (14.09.12 21:55) [0]
    Доброго времени суток
    Задача следующая.

    В таблице в строковом поле сидит дата в формате dd.mm.yyyy.
    Но может там случайно попасть и кракозябра от которой надо защитится (принять дефолтное 01.01.2050) (почему там строка - так надо, база старая и работающая много лет, ответ изменить тип поля не прокатит)
    Мне нужно с єтим значением работать как с datetime.
    Обьічное convert(datetime,isnull(parameter_value, '01.01.2050'),104) не защитит от некоректной датьі
    Если сделать вот так:
    ISDATE(convert(datetime,isnull(parameter_value, '01.01.2050'),104)) и вживить его в case - isdate непонимает формата дд.мм.гггг и если день больше 12 ругается что єто не дата:)

    Буду очень благодарен за оперативньій совет,
    Спасибо
  • lastzealot © (14.09.12 22:05) [1]

    > Если сделать вот так:
    > ISDATE(convert(datetime,isnull(parameter_value, '01.01.2050'),
    > 104)) и вживить его в case

    ^ неправильно написал.

    Словом у меня вот так пока что, но isnull тут путает dd.mm.yyyy c mm.dd.yyyy и дата с днем > 12 идет как 01.01.2050

    convert(datetime, case ISDATE(isnull(parameter_value, '01.01.2050')) when 1 then convert(datetime,  isnull(parameter_value, '01.01.2050'), 104) else convert(datetime, '2050-01-01', 120) end,120)
  • sniknik © (14.09.12 23:58) [2]
    > тут путает dd.mm.yyyy c mm.dd.yyyy
    а не ты? русский и американские стандарты, указания дня... в типах convert должны быть оба.
  • lastzealot © (15.09.12 00:37) [3]
    я не могу загнать в convert значение непроверив его IsDate'ом сначало на адекватность значения поля
    convert(datetime, case ISDATE(isnull(parameter_value, '01.01.2050')) when 1 then convert(datetime,  isnull(parameter_value, '01.01.2050'), 104) else convert(datetime, '2050-01-01', 120) end,120)

    а путает как раз IsDate
  • sniknik © (15.09.12 00:45) [4]
    > а путает как раз IsDate
    не, у него в BOL четко прописано, что он понимает, "нашего" формата там нет

    какая версия mssql-я?

    может и заработает...
    CREATE FUNCTION fn_Date(@val VarChar(50))
    RETURNS DateTime
    AS
    BEGIN
     BEGIN TRY
       RETURN Convert(DateTime, @val, 104);
     END TRY
     BEGIN CATCH
       RETURN 54787
     END CATCH;
    END

  • sniknik © (15.09.12 01:03) [5]
    и да еще SET DATEFORMAT dmy, вроде действует и на ISDATE
  • lastzealot © (15.09.12 01:18) [6]
    Версия 2008
    Имеется внушительньіх размеров сторка в один из селектов которой в where нужно вставить чтото вроде
     parameter_value(тот что как раз в строчном представнении зараза) >= @PeriodFrom

    DATEFORMAT менять похоже не удастся. Датьі там конвертуются и преобразуются почти в каждой строчке. Минимум правок нужно. Думаю даже отдельная новая функция не будет приветствоватся господином db_owner'ом )
  • sniknik © (15.09.12 11:09) [7]
    в 2008 try catch уже поддерживается, не подходит функция так проверь то же самое в пакете команд на выполнение.
    да и DATEFORMAT в пакете можно устанавливать/возвращать, только перегруппировать команды где нужен и "обрамлять" их. если нужно в пределах одного "селекта" то делать его через курсор.
    и т.д., программист ты или кто, в конце концов? возможность есть, а как ее использовать в твоей ситуации это твоя задача решить.

    > Минимум правок нужно.
    это функция. имхо.
  • lastzealot © (15.09.12 14:03) [8]
    в єтом же селекте дейтформат менять нельзя, ибо оспользуеся в американском формате в другой таблице.
    Но решение нашлось:

    ((isnull(ap.PARAMETER_VALUE, '01.01.2050') not like '[0-3][0-9].[0-1][0-9].[0-2][0-9][0-9][0-9]')or(isnull(ap.PARAMETER_VALUE, '01.01.2050') like '[0-3][0-9].[0-1][0-9].[0-2][0-9][0-9][0-9]')and
     (@DateFromLastMonth) <= convert(datetime, case ISDATE(isnull(SUBSTRING(isnull(ap.PARAMETER_VALUE, '01.01.2050'),4,2)+'.'+SUBSTRING(isnull(ap.PARAMETER_VALUE, '01.01.2050'),1,2)+'.'+SUBSTRING(isnull(ap.PARAMETER_VALUE, '01.01.2050'),7,4), '01.01.2050')) when 1 then convert(datetime,  isnull(ap.PARAMETER_VALUE, '01.01.2050'), 104) else convert(datetime, '2050-01-01', 120) end,120))


    или попроще:
    (LEN(isnull(ap.PARAMETER_VALUE, '01.01.2050'))<>10 or LEN(isnull(ap.PARAMETER_VALUE, '01.01.2050'))=10 and
     (@DateFromLastMonth) <= convert(datetime, case ISDATE(isnull(SUBSTRING(isnull(ap.PARAMETER_VALUE, '01.01.2050'),4,2)+'.'+SUBSTRING(isnull(ap.PARAMETER_VALUE, '01.01.2050'),1,2)+'.'+SUBSTRING(isnull(ap.PARAMETER_VALUE, '01.01.2050'),7,4), '01.01.2050')) when 1 then convert(datetime,  isnull(ap.PARAMETER_VALUE, '01.01.2050'), 104) else convert(datetime, '2050-01-01', 120) end,120))



    Вариант подходит, так как отсечение из селекта должно бьіть только если дата в записи меньше переменной, если больше или некоректная - отсечения не будет
  • sniknik © (15.09.12 14:26) [9]
    > [0-3][0-9].[0-1][0-9].[0-2][0-9][0-9][0-9]
    39.19.2999
    like пройдет но это не дата, не правильная дата.
  • sniknik © (15.09.12 14:34) [10]
    > или попроще:
    значение куда "затесалась" кракозябра '15.10.2012#'
    т.е. где срабатывает первое условие
    (LEN(isnull(ap.PARAMETER_VALUE, '01.01.2050'))<>10
 
Конференция "Базы" » T-SQL проверка на коректную дату в европейском формате в строке [MSSQL]
Есть новые Нет новых   [119503   +126][b:0][p:0.002]