Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Conversion failed when converting date and/or time from character string

I have this query :

set IDENTITY_INSERT dbo.OtherData1 ON


INSERT INTO OtherData1 (OtherDataID, EmployeeID, OtherDate, OType, OSubject, StatementNo, StatementDate, Info, OtherAs, FolderSerial)

    SELECT OtherDataID, EmployeeID, 
                 CONVERT(DATE, OtherDate, 103), 
                     OType, OSubject, StatementNo, 
                     CONVERT(DATE, StatementDate), Info,
                     CASE OtherAs
           WHEN  'f' THEN 1
              WHEN  's' THEN 2
              WHEN 't' THEN 3
              WHEN 'f' THEN 4
              WHEN 'p' THEN 5
              WHEN 'o' THEN 6
           ELSE NULL END
           , FolderSerial
    FROM OtherData

I when I execute it I get this error :

Msg 241, Level 16, State 1, Line 5
Conversion failed when converting date and/or time from character string.

the values for StatementDate, OtherDate are in this format "31/1/1994" as string before convert

What is the problem?

EDIT:

if I added this line of code :

CASE WHEN ISDATE(OtherDate) = 1 THEN 
  CONVERT(DATE, OtherDate, 103)
ELSE NULL END

I tried it and it's not working, I need some thing like it to check if vaild do the convert if not insert NULL value and I get the same error message

like image 547
Saleh Avatar asked Feb 26 '11 00:02

Saleh


1 Answers

ISDATE won't work since you cannot even specify a date format as you can with CONVERT. The following is a VERY elaborate test to reformat valid dates into YYYYMMDD for which ISDATE works predictably.

with otherdata(StatementDate) as (
select convert(varchar(10),'1/10/2011') union all
select '28/2/2911' union all
select '8/12/2011' union all
select '13/13/2011' union all
select '13/12/2011' union all
select '12/13/2011' union all
select '2/29/2011' union all
select '29/2/2011' union all
select '29/2/2012' union all
select '2011-02-01' union all
select '1/1/11' union all
select '1/1/99' union all
select '' union all
select null)

-- THE QUERY YOU NEED is below this line. The above virtually sets up a table
-- without having to physically create it
select
    statementdate,
    YYYYMMDDToTest,
    ISDate(YYYYMMDDToTest)
from otherdata
cross apply
       (
       select TheYear = case
       when not statementdate like '%[0-9]/%[0-9]/%[0-9][0-9]' then null
       when convert(int,replace(statementdate,'/','')) != replace(statementdate,'/','') then null
       when statementdate like '%[0-9]/%[0-9]/[0-9][0-9]' then
           case when RIGHT(statementdate,2) >=50
           then '19'+RIGHT(statementdate,2)
           else '20'+RIGHT(statementdate,2)
           end
       when statementdate like '%[0-9]/%[0-9]/[1-9][0-9][0-9][0-9]' then
           RIGHT(statementdate,4)
       end
       ) A
cross apply
       (
       select YYYYMMDDToTest = case
       when TheYear is not null then
           TheYear
           + -- month
           right(100+SUBSTRING(statementdate, charindex('/',statementdate) +1,
           charindex('/',statementdate,charindex('/',statementdate)+1)-
           charindex('/',statementdate)-1),2)
           + -- day
           right(100+LEFT(statementdate, charindex('/', StatementDate) -1),2)
       end
       ) B
WHERE ISDate(YYYYMMDDToTest) = 0

Comment out the last line WHERE ISDate(YYYYMMDDToTest) = 0 to see what it does with each date.


EDIT

You can turn this into a function that replaces the ISDATE - but for the SPECIFIC format [d]d/[m]m/yyyy.

create function dbo.superIs103Date(@any varchar(50))
returns bit as begin
declare @theyear varchar(10)
set @TheYear = case
       when not @any like '%[0-9]/%[0-9]/%[0-9][0-9]' then null
       when convert(int,replace(@any,'/','')) != replace(@any,'/','') then null
       when @any like '%[0-9]/%[0-9]/[0-9][0-9]' then
           case when RIGHT(@any,2) >=50
           then '19'+RIGHT(@any,2)
           else '20'+RIGHT(@any,2)
           end
       when @any like '%[0-9]/%[0-9]/[1-9][0-9][0-9][0-9]' then
           RIGHT(@any,4)
       end
declare @YYYYMMDDToTest varchar(50)
set @YYYYMMDDToTest = case
       when @TheYear is not null then
           @TheYear
           + -- month
           right(100+SUBSTRING(@any, charindex('/',@any) +1,
           charindex('/',@any,charindex('/',@any)+1)-
           charindex('/',@any)-1),2)
           + -- day
           right(100+LEFT(@any, charindex('/', @any) -1),2)
       end
return ISDate(@YYYYMMDDToTest)
end
GO

-- example usage
select dbo.superIs103Date('33/1/1700')
-- returns 0
like image 100
RichardTheKiwi Avatar answered Sep 30 '22 10:09

RichardTheKiwi