To change datetype varchar(14)

  • Dear All,

    i have column in my table which of datatype varchar(14) (20111107070115) , now i want to change display

    2011/11/07 07:01:15 ( DD/MM/YYYY HH:MM:SS)

    please help me on this , i am new to this, i would have like to report on based on this.

    Highly appreciated

  • rashid_alavi (11/27/2011)


    Dear All,

    i have column in my table which of datatype varchar(14) (20111107070115) , now i want to change display

    2011/11/07 07:01:15 ( DD/MM/YYYY HH:MM:SS)

    please help me on this , i am new to this, i would have like to report on based on this.

    Highly appreciated

    You want 24 hour time or 12 hour time?

    As a side bar, this is why one should never store dates and times as VARCHAR... is just makes for a PITA. 😉 Of course, sometimes it's not something that we did and just have to deal with it but it's still a good lesson to learn.

    --Jeff Moden


    RBAR is pronounced "ree-bar" and is a "Modenism" for Row-By-Agonizing-Row.
    First step towards the paradigm shift of writing Set Based code:
    ________Stop thinking about what you want to do to a ROW... think, instead, of what you want to do to a COLUMN.

    Change is inevitable... Change for the better is not.


    Helpful Links:
    How to post code problems
    How to Post Performance Problems
    Create a Tally Function (fnTally)

  • rashid_alavi (11/27/2011)


    Dear All,

    i have column in my table which of datatype varchar(14) (20111107070115) , now i want to change display

    2011/11/07 07:01:15 ( DD/MM/YYYY HH:MM:SS)

    please help me on this , i am new to this, i would have like to report on based on this.

    Highly appreciated

    If you must contain date/time values in a varchar datatype (which is a bad idea), then I'd suggest leaving it in the format YYYYMMDDHHMMSS. This at least allows the column to be properly indexed and ordered. For example:

    select *

    from mytable

    where mydate >= '20111101' and mydate < '20111201'

    order by mydate;

    Any conversion to DD/MM/YYYY should be done on the client/reporting side or perhaps in a view.

    "Do not seek to follow in the footsteps of the wise. Instead, seek what they sought." - Matsuo Basho

  • I agree with the other posts: if possible, change this to a real date type field. Then changing the display in a procedure or application is a simple matter.

    If you can't change how the data is stored in this column, then how about adding a computed column to this table that does store the data as a date type. Then you can base your reports (or whatever) on the computed column.

    If a computed column won't work, then a variation on that theme would be to add a regular date type column and use an AFTER trigger to populate the date column.

  • hi All,

    I Dont want to change on the DB , i want to have that display as YYYY/MM/DD when i want to generate reports for the application reports, the database is MSSQL Server 2005 , i am not getting the right syntax to put it accross.

    appreciate if anyone can give idea on this.

  • rashid_alavi (11/29/2011)


    hi All,

    I Dont want to change on the DB , i want to have that display as YYYY/MM/DD when i want to generate reports for the application reports, the database is MSSQL Server 2005 , i am not getting the right syntax to put it accross.

    appreciate if anyone can give idea on this.

    Then let your application / reports handle it.

  • The issue is what do you do when you have an invalid date? With the data being stored as VARCHAR, you almost certainly will have some invalid dates in there 😉

    Here's some sample data -

    BEGIN TRAN

    SET NOCOUNT ON

    IF object_id('tempdb..#testEnvironment') IS NOT NULL

    BEGIN

    DROP TABLE #testEnvironment

    END

    --1,000,000 Random rows of data

    SELECT TOP 1000000 IDENTITY(INT,1,1) AS ID,

    varcharDateTime

    INTO #testEnvironment

    FROM (SELECT TOP 999999

    REPLACE(REPLACE(REPLACE(CONVERT(VARCHAR(20),(RAND(CHECKSUM(NEWID())) * 30000) + CAST('1945' AS DATETIME),20),'-',''),':',''),' ','') AS varcharDateTime

    FROM master.dbo.syscolumns sc1, master.dbo.syscolumns sc2, master.dbo.syscolumns sc3

    UNION ALL

    SELECT '20190231191114' --INVALID DATE!!

    ) a

    PRINT '========== BASELINE =========='

    SET STATISTICS TIME ON

    SELECT COUNT(*) FROM #testEnvironment

    SET STATISTICS TIME OFF

    PRINT REPLICATE('=',80)

    ROLLBACK

    Here's a couple of SQL options

    PRINT '========== CONVERT ==========' --WILL NOT PICK UP ON THE INVALID DATE I HAVE ADDED

    SET STATISTICS TIME ON

    SELECT SUBSTRING(varcharDateTime,1,4) + '/' + SUBSTRING(varcharDateTime,5,2) + '/' + SUBSTRING(varcharDateTime,7,2) + ' ' +

    SUBSTRING(varcharDateTime,9,2) + ':' + SUBSTRING(varcharDateTime,11,2) + ':' + SUBSTRING(varcharDateTime,13,2),

    varcharDateTime

    FROM #testEnvironment

    SET STATISTICS TIME OFF

    PRINT REPLICATE('=',80)

    PRINT '========== CONVERT WITH CASE ==========' --WILL PICK UP ON THE INVALID DATE I HAVE ADDED

    SET STATISTICS TIME ON

    SELECT formattedVarcharDateTime, varcharDateTime

    FROM (SELECT SUBSTRING(varcharDateTime,1,4) + '/' + SUBSTRING(varcharDateTime,5,2) + '/' + SUBSTRING(varcharDateTime,7,2) + ' ' +

    SUBSTRING(varcharDateTime,9,2) + ':' + SUBSTRING(varcharDateTime,11,2) + ':' + SUBSTRING(varcharDateTime,13,2) AS formattedVarcharDateTime,

    CASE WHEN varcharDateTime NOT LIKE '[1-9][0-9][0-9][0-9][0-1][0-9][0-3][0-9][0-2][0-9][0-5][0-9][0-5][0-9]'

    THEN 0

    WHEN ISDATE(SUBSTRING(varcharDateTime,1,4) + '/' + SUBSTRING(varcharDateTime,5,2) + '/' + SUBSTRING(varcharDateTime,7,2) + ' ' +

    SUBSTRING(varcharDateTime,9,2) + ':' + SUBSTRING(varcharDateTime,11,2) + ':' + SUBSTRING(varcharDateTime,13,2)) <> 1

    THEN 0 ELSE 1 END AS valid, varcharDateTime

    FROM #testEnvironment) a

    WHERE valid = 1

    SET STATISTICS TIME OFF

    PRINT REPLICATE('=',80)

    But I prefer CLR when I have to do something like this. The RegEx function in .Net is much faster at validating this sort of thing (I'll knock one up later on if no-one comes up with a faster solution)


    Forever trying to learn
    My blog - http://www.cadavre.co.uk/
    For better, quicker answers on T-SQL questions, click on the following...http://www.sqlservercentral.com/articles/Best+Practices/61537/
    For better, quicker answers on SQL Server performance related questions, click on the following...http://www.sqlservercentral.com/articles/SQLServerCentral/66909/

  • rashid_alavi (11/29/2011)


    hi All,

    I Dont want to change on the DB , i want to have that display as YYYY/MM/DD when i want to generate reports for the application reports, the database is MSSQL Server 2005 , i am not getting the right syntax to put it accross.

    appreciate if anyone can give idea on this.

    You still haven't said whether you want to display the time as 24 hour time or AM/PM. 😉

    --Jeff Moden


    RBAR is pronounced "ree-bar" and is a "Modenism" for Row-By-Agonizing-Row.
    First step towards the paradigm shift of writing Set Based code:
    ________Stop thinking about what you want to do to a ROW... think, instead, of what you want to do to a COLUMN.

    Change is inevitable... Change for the better is not.


    Helpful Links:
    How to post code problems
    How to Post Performance Problems
    Create a Tally Function (fnTally)

  • Cadavre (11/29/2011)


    But I prefer CLR when I have to do something like this. The RegEx function in .Net is much faster at validating this sort of thing (I'll knock one up later on if no-one comes up with a faster solution)

    Sometimes, that's true. Sometimes, it's not. Matt Miller and I did some extreme testing (admittedly, several years ago) between the use of RegEx CLRs and validating data in T-SQL. There were many things where T-SQL beat the tar out of the CLRs.

    --Jeff Moden


    RBAR is pronounced "ree-bar" and is a "Modenism" for Row-By-Agonizing-Row.
    First step towards the paradigm shift of writing Set Based code:
    ________Stop thinking about what you want to do to a ROW... think, instead, of what you want to do to a COLUMN.

    Change is inevitable... Change for the better is not.


    Helpful Links:
    How to post code problems
    How to Post Performance Problems
    Create a Tally Function (fnTally)

  • Jeff Moden (11/29/2011)


    Cadavre (11/29/2011)


    But I prefer CLR when I have to do something like this. The RegEx function in .Net is much faster at validating this sort of thing (I'll knock one up later on if no-one comes up with a faster solution)

    Sometimes, that's true. Sometimes, it's not. Matt Miller and I did some extreme testing (admittedly, several years ago) between the use of RegEx CLRs and validating data in T-SQL. There were many things where T-SQL beat the tar out of the CLRs.

    Agreed, but in my testing I've found the reverse to be true more often. However CLR comes with extra problems, in that so far 100% of the DBAs I've worked under have refused to allow CLRs anywhere near their server 😀


    Forever trying to learn
    My blog - http://www.cadavre.co.uk/
    For better, quicker answers on T-SQL questions, click on the following...http://www.sqlservercentral.com/articles/Best+Practices/61537/
    For better, quicker answers on SQL Server performance related questions, click on the following...http://www.sqlservercentral.com/articles/SQLServerCentral/66909/

  • preferrable 24 hours time. and its ok if you can provide 12 hours time as well

  • rashid_alavi (11/29/2011)


    hi All,

    I Dont want to change on the DB , i want to have that display as YYYY/MM/DD when i want to generate reports for the application reports, the database is MSSQL Server 2005 , i am not getting the right syntax to put it accross.

    appreciate if anyone can give idea on this.

    There is a T-SQL function called CONVERT which can accept a datetime value and return a formatted string. This is problematic, because your initial string value of YYYYMMDDHHMMSS must first be converted into a datetime, but before that, the HHMMSS must be stuffed with colons. Yuck!

    There is also a function called STUFF which can embed a string (like a colon or slash) into another string. You transform your "date" string using a combination of CONVERT and STUFF, or just use a combination of several STUFFs.

    Here are a couple of examples:

    declare @mytable table (mydate varchar(14));

    insert into @mytable ( mydate ) values ('20111107070115');

    select

    stuff(stuff(substring(mydate,1,8),5,0,'/'),8,0,'/') as mydate1,

    replace(convert(varchar(22),cast(stuff(stuff(stuff(

    mydate,9,0,' '),12,0,':'),15,0,':') as datetime),120),'-','/') as mydate2

    from @mytable;

    mydate1 mydate2

    ---------- -------------------

    2011/11/07 2011/11/07 07:01:15

    You can perform this transform in the SELECT statement, or as someone previously suggested, implement it as a computed column within the table itself. A computed column would avoid the possibility of having to put the transform in multiple SELECT statements, if several different reports need to use it.

    "Do not seek to follow in the footsteps of the wise. Instead, seek what they sought." - Matsuo Basho

  • Here's a few different methods.

    BEGIN TRAN

    SET NOCOUNT ON

    IF object_id('tempdb..#testEnvironment') IS NOT NULL

    BEGIN

    DROP TABLE #testEnvironment

    END

    --1,000,000 Random rows of data

    SELECT TOP 1000000 IDENTITY(INT,1,1) AS ID,

    varcharDateTime

    INTO #testEnvironment

    FROM (SELECT TOP 999999

    REPLACE(REPLACE(REPLACE(CONVERT(VARCHAR(20),(RAND(CHECKSUM(NEWID())) * 30000) + CAST('1945' AS DATETIME),20),'-',''),':',''),' ','') AS varcharDateTime

    FROM master.dbo.syscolumns sc1, master.dbo.syscolumns sc2, master.dbo.syscolumns sc3

    UNION ALL

    SELECT '20190231191114' --INVALID DATE!!

    ) a

    --HOLDER TO TAKE THE DISPLAY TIME OUT OF THE EQUATION

    DECLARE @TEST VARCHAR(100)

    PRINT '========== BASELINE =========='

    SET STATISTICS TIME ON

    SELECT @TEST = COUNT(*) FROM #testEnvironment

    SET STATISTICS TIME OFF

    PRINT REPLICATE('=',80)

    PRINT '========== CONVERT WITH CASE ==========' --WILL PICK UP ON THE INVALID DATE I HAVE ADDED

    SET STATISTICS TIME ON

    SELECT @TEST = formattedVarcharDateTime

    FROM (SELECT SUBSTRING(varcharDateTime,1,4) + '/' + SUBSTRING(varcharDateTime,5,2) + '/' + SUBSTRING(varcharDateTime,7,2) + ' ' +

    SUBSTRING(varcharDateTime,9,2) + ':' + SUBSTRING(varcharDateTime,11,2) + ':' + SUBSTRING(varcharDateTime,13,2) AS formattedVarcharDateTime,

    CASE WHEN varcharDateTime NOT LIKE '[1-9][0-9][0-9][0-9][0-1][0-9][0-3][0-9][0-2][0-9][0-5][0-9][0-5][0-9]'

    THEN 0

    WHEN ISDATE(SUBSTRING(varcharDateTime,1,4) + '/' + SUBSTRING(varcharDateTime,5,2) + '/' + SUBSTRING(varcharDateTime,7,2) + ' ' +

    SUBSTRING(varcharDateTime,9,2) + ':' + SUBSTRING(varcharDateTime,11,2) + ':' + SUBSTRING(varcharDateTime,13,2)) <> 1

    THEN 0 ELSE 1 END AS valid, varcharDateTime

    FROM #testEnvironment) a

    WHERE valid = 1

    SET STATISTICS TIME OFF

    PRINT REPLICATE('=',80)

    PRINT '========== CONVERT WITH CLR ==========' --WILL PICK UP ON THE INVALID DATE I HAVE ADDED

    SET STATISTICS TIME ON

    SELECT @TEST = SUBSTRING(varcharDateTime,1,4) + '/' + SUBSTRING(varcharDateTime,5,2) + '/' + SUBSTRING(varcharDateTime,7,2) + ' ' +

    SUBSTRING(varcharDateTime,9,2) + ':' + SUBSTRING(varcharDateTime,11,2) + ':' + SUBSTRING(varcharDateTime,13,2)

    FROM (SELECT dbo.ReplaceMatch(varcharDateTime,

    '^([1-9]\d{3}((0[1-9]|1[012])(0[1-9]|1\d|2[0-8])|(0[13456789]|1[012])(29|30)|(0[13578]|1[02])31)|(([2-9]\d)(0[48]|[2468][048]|[13579][26])|(([2468][048]|[3579][26])00))0229)(([0-1][0-9])|(2[0-3]))([0-5][0-9])([0-5][0-9])',

    varcharDateTime) AS varcharDateTime

    FROM #testEnvironment) a

    WHERE varcharDateTime IS NOT NULL

    SET STATISTICS TIME OFF

    PRINT REPLICATE('=',80)

    PRINT '========== CONVERT WITH REPLACE ==========' --WILL NOT PICK UP ON THE INVALID DATE I HAVE ADDED

    SET STATISTICS TIME ON

    SELECT @TEST = REPLACE(CONVERT(VARCHAR(22), CAST(STUFF(STUFF(STUFF(

    varcharDateTime, 9, 0, ' '), 12, 0, ':'), 15, 0, ':') AS DATETIME), 120), '-', '/')

    FROM #testEnvironment

    SET STATISTICS TIME OFF

    PRINT REPLICATE('=',80)

    PRINT '========== CONVERT WITH REPLACE AND CLR ==========' --WILL PICK UP ON THE INVALID DATE I HAVE ADDED

    SET STATISTICS TIME ON

    SELECT @TEST = REPLACE(CONVERT(VARCHAR(22), CAST(STUFF(STUFF(STUFF(

    varcharDateTime, 9, 0, ' '), 12, 0, ':'), 15, 0, ':') AS DATETIME), 120), '-', '/')

    FROM (SELECT dbo.ReplaceMatch(varcharDateTime,

    '^([1-9]\d{3}((0[1-9]|1[012])(0[1-9]|1\d|2[0-8])|(0[13456789]|1[012])(29|30)|(0[13578]|1[02])31)|(([2-9]\d)(0[48]|[2468][048]|[13579][26])|(([2468][048]|[3579][26])00))0229)(([0-1][0-9])|(2[0-3]))([0-5][0-9])([0-5][0-9])',

    varcharDateTime) AS varcharDateTime

    FROM #testEnvironment) a

    WHERE varcharDateTime IS NOT NULL

    SET STATISTICS TIME OFF

    PRINT REPLICATE('=',80)

    PRINT '========== CONVERT WITH REPLACE AND CASE ==========' --WILL PICK UP ON THE INVALID DATE I HAVE ADDED

    SET STATISTICS TIME ON

    SELECT @TEST = REPLACE(CONVERT(VARCHAR(22), CAST(STUFF(STUFF(STUFF(

    varcharDateTime, 9, 0, ' '), 12, 0, ':'), 15, 0, ':') AS DATETIME), 120), '-', '/')

    FROM (SELECT varcharDateTime,

    CASE WHEN varcharDateTime NOT LIKE '[1-9][0-9][0-9][0-9][0-1][0-9][0-3][0-9][0-2][0-9][0-5][0-9][0-5][0-9]'

    THEN 0

    WHEN ISDATE(SUBSTRING(varcharDateTime,1,4) + '/' + SUBSTRING(varcharDateTime,5,2) + '/' + SUBSTRING(varcharDateTime,7,2) + ' ' +

    SUBSTRING(varcharDateTime,9,2) + ':' + SUBSTRING(varcharDateTime,11,2) + ':' + SUBSTRING(varcharDateTime,13,2)) <> 1

    THEN 0 ELSE 1 END AS valid

    FROM #testEnvironment) a

    WHERE valid = 1

    SET STATISTICS TIME OFF

    PRINT REPLICATE('=',80)

    ROLLBACK

    ========== BASELINE ==========

    SQL Server Execution Times:

    CPU time = 78 ms, elapsed time = 70 ms.

    ================================================================================

    ========== CONVERT WITH CASE ==========

    SQL Server Execution Times:

    CPU time = 7969 ms, elapsed time = 8018 ms.

    ================================================================================

    ========== CONVERT WITH CLR ==========

    SQL Server Execution Times:

    CPU time = 16016 ms, elapsed time = 16539 ms.

    ================================================================================

    ========== CONVERT WITH REPLACE ==========

    Msg 242, Level 16, State 3, Line 59

    The conversion of a varchar data type to a datetime data type resulted in an out-of-range value.

    SQL Server Execution Times:

    CPU time = 4516 ms, elapsed time = 4531 ms.

    ================================================================================

    ========== CONVERT WITH REPLACE AND CLR ==========

    SQL Server Execution Times:

    CPU time = 22141 ms, elapsed time = 22725 ms.

    ================================================================================

    ========== CONVERT WITH REPLACE AND CASE ==========

    SQL Server Execution Times:

    CPU time = 11516 ms, elapsed time = 11535 ms.

    ================================================================================

    I could do with tuning all of it (especially the CLR), but it should be enough to get you started.


    Forever trying to learn
    My blog - http://www.cadavre.co.uk/
    For better, quicker answers on T-SQL questions, click on the following...http://www.sqlservercentral.com/articles/Best+Practices/61537/
    For better, quicker answers on SQL Server performance related questions, click on the following...http://www.sqlservercentral.com/articles/SQLServerCentral/66909/

  • I Dont want to change on the DB , i want to have that display as YYYY/MM/DD when i want to generate reports for the application reports, the database is MSSQL Server 2005 , i am not getting the right syntax to put it accross.

    One way to do this, would be to use a CAST function to convert the string to a date, like so

    CAST([DateString] AS DATETIME)

    CAST will take a string in any valid date and time format, and convert it to a date-time field. Then embed that function in a CONVERT function to display the data the way you want it. CONVERT allows you to specify a style for displaying date and time strings. The style you have specified is pretty close to the ODBC canonical style (YYYY-MM-DD hh:mm:ss 24 hour format). That is style 120 in T-SQL. So, the final function would look like this.

    CONVERT(VARCHAR(19), CAST([DateString] AS DATETIME), 120)

    As the other posters have said, your main problem will be dealing with improperly formatted data. However, this function should do as you have requested.

  • David Moutray (11/29/2011)


    I Dont want to change on the DB , i want to have that display as YYYY/MM/DD when i want to generate reports for the application reports, the database is MSSQL Server 2005 , i am not getting the right syntax to put it accross.

    One way to do this, would be to use a CAST function to convert the string to a date, like so

    CAST([DateString] AS DATETIME)

    CAST will take a string in any valid date and time format, and convert it to a date-time field. Then embed that function in a CONVERT function to display the data the way you want it. CONVERT allows you to specify a style for displaying date and time strings. The style you have specified is pretty close to the ODBC canonical style (YYYY-MM-DD hh:mm:ss 24 hour format). That is style 120 in T-SQL. So, the final function would look like this.

    CONVERT(VARCHAR(19), CAST([DateString] AS DATETIME), 120)

    As the other posters have said, your main problem will be dealing with improperly formatted data. However, this function should do as you have requested.

    The wrinkle is that "20111107070115" won't CAST to datetime as is. He has to first STUFF a space before the time portion and some colons between the HH:MM:SS.

    "Do not seek to follow in the footsteps of the wise. Instead, seek what they sought." - Matsuo Basho

Viewing 15 posts - 1 through 15 (of 17 total)

You must be logged in to reply to this topic. Login to reply