Find records with specific date format - sql

I want to select all records that are not in format yyyy-mm-dd. Datatype of column is varchar.
Update the records in step 1 with the correct format(yyyy-mm-dd).
I have tried filtering with function: IsDate() but got no success.
Create table
CREATE TABLE #tempdate (dateCol varchar(50));
INSERT INTO #tempdate VALUES
('2019-05-13 16:55:47:284'),
('2019-04-05 14:08:10.060'),
('6/19/2018 12:35:53 PM'),
('2019-05-13');

Use try_cast()
select try_cast(datecol as date)

You can try below -
update #tempdate set datecol=format(cast(dateCol as date),'yyyy-mm-dd')

The most important answer was given by EzLo in a comment above: Do not store date/time values in a string format.
A native date/time type is stored in a non-readable, binary pattern. Any action will be faster and secure against culture dependency.
The readable format is something for the output only and should be done in exports or within your presentation layer.
If you have to stick with this (or if this is your attempt to clean and transform your data to a correct format), I'd suggest one of those:
SELECT *
FROM #tempdate
--either use a text base pattern
WHERE LEFT(dateCol,10) NOT LIKE '[1,2][0-9][0-9][0-9]-[0,1][0-9]-[0-3][0-9]';
--or use a fixed conversion format (here I use 126 for ISO8601)
WHERE TRY_CONVERT(date,dateCol,126) IS NULL

1.
SELECT * FROM #tempdate
WHERE ISDATE(dateCol)= 1 AND CHARINDEX('-',dateCol) = 5
2.
UPDATE #tempdate
SET datecol = CONVERT(DATETIME,datecol,102)
WHERE ISDATE(dateCol)= 1
SELECT * FROM #tempdate

Please Try the below.
update #tempdate set datecol=Convert(char(10),convert(datetime,datecol,120),126)
Please let me know
Thanks

Related

Why isn't SQL Server letting me store '21/04/17' as a date?

I've got a table that currently has all columns stored as nvarchar(max), so I'm converting all the datatypes to be what they should be. I have a column of dates, however when I run this:
ALTER TABLE Leavers ALTER COLUMN [Actual_Termination_Date] date;
I get
"Conversion failed when converting date and/or time from character string".
This is relatively normal, so I did the following to investigate:
SELECT DISTINCT TOP 20 [Actual_Termination_Date]
FROM LEAVERS
WHERE ISDATE([Actual_Termination_Date]) = 0
which returned:
NULL
13/04/2017
14/04/2017
17/04/2017
19/04/2017
21/04/2017
23/04/2017
24/04/2017
26/04/2017
28/04/2017
29/03/2017
29/04/2017
30/04/2017
31/03/2017
42795
42797
42813
42817
42820
42825
The null and excel style date formats (e.g. 42795) are no problem, however it's the ones appearing as perfectly normal dates I'm having a problem with. I usually fix issues like this by using one of the following fixes:
SELECT cast([Actual_Termination_Date] - 2 as datetime)
FROM LEAVERS
WHERE ISDATE([Actual_Termination_Date]) = 0
or
SELECT cast(convert(nvarchar,[Actual_Termination_Date], 103) - 2 as datetime)
FROM LEAVERS
WHERE ISDATE([Actual_Termination_Date]) = 0
When these return back the dates as I would expext, I'd then do an UPDATE statement to change them in the table and then convert the column type. However I keep getting an error message telling me that various dates can't be converted such as:
Conversion failed when converting the nvarchar value '21/04/2017' to data type int.
Any thoughts? Thanks!
Probably because of your language setting. For '21/04/2017' to work, you'll need to be using the BRITISH language, or other language that uses dd/MM/yyyy. I suspect you are using ENGLISH which is actually American.
American's use MM/dd/yyyy meaning that '21/04/2017' would mean the 4th day of the 21st month in the year 2017; obviously that doesn't work.
The best method is to use an unambiguous format, regardless of language and data type. For SQL Server that's yyyyMMdd and yyyy-MM-ddThh:mm:ss.nnnnnnn (yyyy-MM-dd and yyyy-MM-dd hh:mm:ss.nnnnnnn are not unambiguous in SQL Server when using the older datetime and smalldatetime data types).
Otherwise you can use CONVERT with a style code:
SELECT CONVERT(date,'21/04/2017', 103)
The problem with your data, however, is that you have values that are in the format dd/MM/yyyy and integer values. The int (not varchar) value 42817 as a datetime in SQL Server is 2017-03-25. On the other hand, if this data came from Excel then the value is 2017-03-23. I am going to assume the data came from Excel, not SQL Server (because the ACE drivers have a habit of reading dates as numbers, because the thing they aren't is "ace").
You'll need to therefore convert the values to an unambiguous format first, so that'll be yyyyMMdd. As we have 2 different types of values, this is a little harder, but still possible:
UPDATE dbo.Leavers
SET Actual_Termination_Date = CONVERT(varchar(8), ISNULL(TRY_CONVERT(date, Actual_Termination_Date, 103), DATEADD(DAY, TRY_CONVERT(int, Actual_Termination_Date),'18991230')), 112);
Then you can alter your table:
ALTER TABLE dbo.Leavers ALTER COLUMN [Actual_Termination_Date] date;
DB<>Fiddle using MichaƂ Turczyn's DML statement.
Put the column into a canonical format first, then convert:
update leavers
set Actual_Termination_Date = try_convert(date, [Actual_Termination_Date], 103);
ALTER TABLE Leavers ALTER COLUMN [Actual_Termination_Date] date;
The update will do an implicit conversion from the date to a string. The alter should be able to "undo" that implicit conversion.
Back up the table before you do this! You are likely to discover that some dates are not valid -- that is pretty much the rule when you store dates as strings although in a small minority of cases, all date strings are actually consistently formatted.
The actual date does not matter. The error happens when you try to subtract 2 from a string:
[Actual_Termination_Date] - 2
The clue comes from the error message:
Conversion failed when converting the nvarchar value '21/04/2017' to data type int.
To fix the problem, use DATEADD after the conversion:
SELECT DATEADD(days, -2, convert(datetime, [Actual_Termination_Date], 103))
You just have inconsistent date format within your column, which is terrible.
Having wrong datatype lead to it, that's why it is so important to have proper data types on columns.
Let's investigate it a little:
-- some test data
declare #tbl table (dt varchar(20));
insert into #tbl values
(NULL),
('13/04/2017'),
('14/04/2017'),
('17/04/2017'),
('19/04/2017'),
('21/04/2017'),
('23/04/2017'),
('24/04/2017'),
('26/04/2017'),
('28/04/2017'),
('29/03/2017'),
('29/04/2017'),
('30/04/2017'),
('31/03/2017'),
('42795'),
('42797'),
('42813'),
('42817'),
('42820'),
('42825');
-- here we handle one format
select convert(date, dt, 103) from #tbl
where len(dt) > 5
or dt is null
-- here we handle excel like format
select dateadd(day, cast(dt as int), '1900-01-01') from #tbl
where len(dt) = 5
So, as you can see you have to apply to different approaches for this task. CASE WHEN statement should fit here nicely, see below SELECT:
select case when len(dt) = 5 then
dateadd(day, cast(dt as int), '1900-01-01')
else convert(date, dt, 103) end
from #tbl

Convert Date datatype to datetime datatype and add static time

I'm at my wits end... Hope you all can help. I have a date column entryexpire in sql table, eg:
2013-04-12
I need to convert it to a datetime with all values in entryexpire to have 24:00:00 appended to new values, eg:
2103-04-12 24:00:00
I've tried cast, covert, adding new columns and concatenation ... All failed me.
Add new column col2 (Datetime). Issue update:
update table t1 set col2 = cast(col1, datetime) // db specific function
Drop column Col1.
Rename col2 to col1
I mean, there are few other ways of doing it as well
24:00:00 is not really an option for a date - you'd be into the next day. Here's a select statement you can use to tailor a date to your needs, but about the closest you will get to the end of the day is 23:59:59.997
DECLARE #MYDATE varchar(50) = '2013-04-12'
SELECT DATEADD(DAY,1,DATEADD(Ms,-2, CAST(#MYDATE AS DATETIME)))
This returns 2013-04-12 23:59:59.997
Alternately, you could have two different varchar columns (which it seems you tried), and query them like this to get a datetime
DECLARE #MYDATE varchar(50) = '2013-04-12'
declare #mytime varchar(50) = ' 23:59:59.998'
select CAST(#mydate + #mytime as datetime)
Again, using 23:59:59.999 causes the select to return 2013-04-13 00:00:00.000. Not sure why.
If anyone had same problem this is how i solved. I created a char column
temptime
and added a value of 23:59:00 to all records in database into that column with an update command.
i then created another column as datetime
entryexpiredatetime
with my entryexpiredate as a char and temptime as char column i used #folksymAndrews code as follows:
Blockquote
update [table] set entryexpiredatetime = CAST(ENTRYEXPIREDATE+timetime as datetime)
Blockquote
then i dropped temptime column and was left with my original entryexpiredate and my needed entryexpiredatetime columns.
Thanks for all your help. This was the best way i felt i could accomplish the task but im sure there is a less invasion way.

SQL Server 2008 - convert varchar to datetime column

I have a table with a varchar column (dateandtime) with date and time in the format dd/mm/yyyy hh:mm:ss and I need to convert it to a datetime column.
I have a temp column dateandtimetemp in the table .
Thanks
Try this:
SELECT CONVERT(Datetime, '15/05/2013 13:55:12', 104)
It should return : 2013-05-15 13:55:12.000
Try
SELECT CONVERT(VARCHAR(30),GETDATE(),113) ;
it return result in following format
15 May 2013 16:26:29:850
So then just go ahead and try it!
UPDATE dbo.YourTable
SET DateAndTimeTemp = CAST(DateAndTime AS DATETIME)
and see if it works. If your input data is really always properly defined - you should have no issues here.
This of course depends on what langauge/dateformat setting you have activated in your database - so that might be the first problem you encounter.
If you do have issues, then you can always "clean up" your input data and try again ...
Try this
SELECT CONVERT(DATETIME, '15/05/2013 11:12:13', 103)

SQL Fastest way to compare two dates (non standard varchar format and datetime)

I have two "date" fields that I need to join on.
The first is a normal datetime in the format yyyy-mm-dd hh:mm:ss
The second is a varchar(8) in the red-headed step child format mmddyyyy
Now this gets painful because there is no easy way to convert to the corresponding type. There is a built-in format that is yyyymmdd but that doesn't match the varchar format.
There are two paths I can see:
declare #normal_date as datetime;
declare #hated_date as varchar(8);
set #normal_date='1974-11-01 00:00:00.000'
set #hated_date='11011974'
--cast to date time with string splits
select #normal_date
where CONVERT(datetime, RIGHT(#hated_date,4)+LEFT(#hated_date,2)+SUBSTRING(#hated_date,3,2))=#normal_date
--convert normal date to ackward format
select #normal_date
where REPLACE(CONVERT(varchar(10),#normal_date,101), '/','')=#hated_date
Which is better? Or is there a better way?
Edited to show costs
--Operator cost (39%)
CONVERT(datetime, RIGHT(#hated_date,4)+LEFT(#hated_date,2)+SUBSTRING(#hated_date,3,2))=#normal_date
--Operator cost (57%)
REPLACE(CONVERT(varchar(10),#normal_date,101), '/','')=#hated_date
--Operator cost (46%)
cast(stuff(stuff(#hated_date, 3,0, '/'),6,0,'/') as datetime)=#normal_date
--Operator cost (47%)
RIGHT(#hated_date, 4) + LEFT(#hated_date, 4)=#normal_date
This is yyyymmdd no?
RIGHT(#hated_date, 4) + LEFT(#hated_date, 4)
So, your script becomes
declare #normal_date as datetime;
declare #hated_date as varchar(8);
set #normal_date='1974-11-01 00:00:00.000'
set #hated_date='11011974'
--SELECT #hated_date = RIGHT(#hated_date, 4) + LEFT(#hated_date, 4))
select 'hurrah' WHERE #normal_date = RIGHT(#hated_date, 4) + LEFT(#hated_date, 4)
Another approach is this:
MONTH(#normal_date)*1000000 + DAY(#normal_date)*10000 + YEAR(#normal_date)
=
CAST(#hated_date AS INT)
one more thing: it is more precise to compare real execution costs than to rely on the optimizer's estimates.
Try this:
select cast(stuff(stuff('11011974', 3,0, '/'),6,0,'/') as datetime)
Update
Suggest you either fix the column to be datetime or add a datetime column to the table and convert the data so that you only have to do this conversion once when the data is entered (and once of course for existing data) This could probaly even be a calculated column. This is NOT something you want to be doing in select statements. If necessary create a dateconversion table with every opossible date in both formates and join to it if the table can't be changed.
You might also want to check to make sure there are no invalid dates in there which is always a possibility with storing dates in a data type other than a datetime one.

How do you update a DateTime field in T-SQL?

The following query does not update the datetime field:
update table
SET EndDate = '2009-05-25'
WHERE Id = 1
I also tried it with no dashes, but that does not work either.
When in doubt, be explicit about the data type conversion using CAST/CONVERT:
UPDATE TABLE
SET EndDate = CAST('2009-05-25' AS DATETIME)
WHERE Id = 1
Normally, it should work.
But can you try this? I don't have SQL on my home PC, I can't try myself
UPDATE table
SET EndDate = '2009-05-25 00:00:00.000'
WHERE Id = 1
The string literal is pased according to the current dateformat setting, see SET DATEFORMAT. One format which will always work is the '20090525' one.
Now, of course, you need to define 'does not work'. No records gets updated? Perhaps the Id=1 doesn't match any record...
If it says 'One record changed' then perhaps you need to show us how you verify...
Using a DateTime parameter is the best way.
However, if you still want to pass a DateTime as a string, then the CAST should not be necessary provided that a language agnostic format is used.
e.g.
Given a table created like :
create table t1 (id int, EndDate DATETIME)
insert t1 (id, EndDate) values (1, GETDATE())
The following should always work :
update t1 set EndDate = '20100525' where id = 1 -- YYYYMMDD is language agnostic
The following will work :
SET LANGUAGE us_english
update t1 set EndDate = '2010-05-25' where id = 1
However, this won't :
SET LANGUAGE british
update t1 set EndDate = '2010-05-25' where id = 1
This is because 'YYYY-MM-DD' is not a language agnostic format (from SQL server's point of view) .
The ISO 'YYYY-MM-DDThh:mm:ss' format is also language agnostic, and useful when you need to pass a non-zero time.
More info : http://karaszi.com/the-ultimate-guide-to-the-datetime-datatypes
UPDATE TABLE
SET EndDate = CAST('2017-12-31' AS DATE)
WHERE Id = '123'
If you aren't interested in specifying a time, you can also use the format 'DD/MM/YYYY', however I would stick to a Conversion method, and its relevant ISO format, as you really should avoid using default values.
Here's an example:
SET startDate = CONVERT(datetime,'2015-03-11T23:59:59.000',126)
WHERE custID = 'F24'
That should work, I'd put brackets around [Date] as it's a reserved keyword.
Is there maybe a trigger on the table setting it back?