Convert Varchar to Date type (not just to run a query, actually changing the column on the table) - sql

This was asked several times but I wasn't able to implement any of the answers.
I have a table with a column with Dates that has been created as VARCHAR, I want to convert it to Date(103).
I've seen several responses with the following:
SELECT CONVERT(VARCHAR(10), GETDATE(), 103) AS [DD/MM/YYYY]
This will work nicely to convert the result of a query...but I want to convert the actual column not just when I do a select query.
I probably just don't understand where to put this line of SQL code. Can anyone help me out?

There is no such thing as DATE(103); dates are stored using an internal format. I'll assume that is the format of the string.
What to do? Change the string to something that can be implicitly converted to a date. Then change the column:
update t
set datecol = convert(date, datecol, 103);
alter t alter datecol date;
If this returns an error, you need to figure out where the values don't convert properly. That would use:
select datecol
from t
where try_convert(date, datecol, 103) is null and
datecol is not null;
You'll need to figure out how to fix the broken values. And in the process learn one important reason not to store date/time values as strings.

Related

How to find the wrong dates after an 'out-of-range value' error in SQL Server?

I want to convert a column in the format mm/dd/yyyy to datetime, but when I do I get the following error:
The conversion of a varchar data type to a datetime data type resulted in an out-of-range value.
I found in other posts that this means that some dates don't make sense, such as 10/35/2021. I tried to find the wrong dates by slicing the varchars to get the dates with SUBSTRING(date, 3, 2) but it turns out some dates are in the form m/d/yyyy, so when I slice I get something like 1/.
I have no idea how to find the wrong dates, and how to (even though there are wrong dates) convert everything to datetime.
Thanks!
If some of your data is in MM/dd/YYYY and some M/d/yyyy this really makes for a bit of a mess. I would likely do something like this:
--Add a new varchar column (yes varchar) to save a copy of your bad data
ALTER TABLE dbo.YourData ADD BadDate varchar(10);
GO
--Change the data you have to the ISO format yyyyMMdd and store the bad data in the BadDate column
UPDATE dbo.YourData
SET DateColumn = CONVERT(varchar(8),TRY_CONVERT(date,DateColumn,101),112),
BadDate = CASE WHEN TRY_CONVERT(date,DateColumn,101) IS NULL THEN DateColumn END
WHERE DateColumn IS NOT NULL;
GO
--Change data type of your data column
ALTER TABLE dbo.YourData ALTER COLUMN DateColumn date NULL;
GO
--You can view your bad data with:
SELECT BadData
FROM dbo.YourData
WHERE BadData IS NOT NULL;
If you just want to locate rows with values that are obviously bad dates - disregarding any ambiguities - just use try_convert and check for NULLs
eg
with dates as (
select * from (values('01/02/2021'),('02/01/2021'),('33/02/2021'),('01/13/2021'))v(d)
)
select *
from dates
where Try_Convert(date, d) is null

Convert column with data MM/DD/YYYY varchar to date in sql server?

I've found some similar questions but haven't been able to get anything to work yet. I'm very much a novice with little SQL experience.
I have a column END_DATE as Varchar(10) where all the rows follow the mm/dd/yyyy format and I would like to convert it to date. I have an empty column formatted as date if that helps. There are 36 million rows.
SELECT CONVERT(DATETIME,YourColumn,101) FROM YourTable
101 is mm/dd/yyyy format.
You zany backwards americans :)
To update your existing column
UPDATE YourTable
SET YourNewColumn = CONVERT(DATETIME,YourOldColumn,101)
Since it appears you have invalid data, use this method to isolate it:
UPDATE YourTable
SET YourNewColumn = CONVERT(DATETIME,YourOldColumn,101)
WHERE SomeTableKey BETWEEN ASmallCode AND ABiggerCode
Find a key in your table that you can use to divide up the data and try updating half the table... now halve it again and again until you find the offending data. Post the data here and we will come up with some code to allow for it.
I think you should convert END_DATE to DATETIME type, because you have 36 million rows and it will give a performance boost when you do not have to cast or convert it datetime with select statement.
To answer your question, you can do something like
select CAST(END_DATE AS DATETIME) FROM MyTable
The PARSE (SQL 2012) or CONVERT (any version) can do the conversion for you. Your UPDATE query will look something like one of these statements:
UPDATE the_table SET the_column = PARSE(end_date AS datetime2 USING 'en-US')
UPDATE the_table SET the_column = CONVERT(datetime2, end_date, 101)
DECLARE #End_DATE VARCHAR(10);
SET #End_DATE = '12/20/2013';
SELECT CAST(#End_DATE AS DATE)
RESULT: 2013-12-20
Empty Column formatted as Date, I am guessing you meant to say you have DATE datatype column and you would like to update this VARCHAR(10) date to , Date datatype column you could do something like this....
UPDATE Table_Name
SET New_End_DATE = CAST(End_DATE AS DATE)
Working SQL FIDDLE

Converting datetime to short date from a declared table in sql

This is my first question on StackOverflow so I apologize for this most likely being formatted incorrectly. I am very new to sql language and am having trouble with the following query:
I have a declared table with one row selecting for a datetime (OccurrenceGroupID) and would like to have that date show up with short date formatting in the query results.
--Select for Occurrence Group
Declare #A3 table (OccurrenceGroupID datetime)
insert into #A3
select OccurrenceGroup as OccurrenceGroup,
Convert(VARCHAR(10),GETDATE(), 101) as [MM/DD/YYYY]
from tblOccurrenceGroup
where occurrencegroupid = #occurrencegroupid
I get the error message "Column name or number of supplied values does not match table definition."
Any help would be much appreciated.
Thanks.
Your error is because you are selecting two columns and trying to insert the result set into a table with only one column.
Regardless of this you are converting a datetime to a varchar presumably for presentation reasons and then wanting to insert it into a column of type datetime which doesn't make much sense. Always leave the formatting of dates to the client application.
you have declared it as datetime
Declare #A3 table (OccurrenceGroupID datetime)
so it expects a date and a time you the go on to say
Convert(VARCHAR(10),GETDATE(), 101) as [MM/DD/YYYY]
you then say convert the varchar as MM/DD/YYYY therefor it is contradictory to your first statement

converting varchar to date format in sql server

I have a table with two date column. However the columns are in varchar. I need to covert them as date format.
The sample data is like this:
Account Number | Registration Date | System Status Change Date
01740567715 | 10-JUL-13 | 30-JUL-13 12.53.32.000000000 PM
I want both of these columns like this: 10-Jul-2013.
For Registration Date, I am using this code:
Update [dbo].[SysDataV2]
Set ["REGISTRATION_DATE"]= convert(datetime, (["REGISTRATION_DATE"]), 106)
But it is shwoing the result as varchar and also showing erroneous format.
For System Status Change Date I am using following code:
update [dbo].[SysData]
Set ["KYC_STATUS_CHANGED_DATE"]= REPLACE(CONVERT(datetime,convert(datetime,left(["KYC_STATUS_CHANGED_DATE"],9),103),106),' ' ,'-')
Both are changing to date format of some type (not my expected format) but in table structure they are still shown as varchar.
What am I doing wrong here?
The table's data type is still varchar. An update merely changes the string, it doesn't change the data type. What you should do is (assuming all of the dates are valid and this format is 100% consistent):
UPDATE dbo.SysData SET REGISTRATION_DATE =
CONVERT(CHAR(10), CONVERT(DATE, REGISTRATION_DATE, 106), 120);
UPDATE dbo.SysData SET KYC_STATUS_CHANGED_DATE =
CONVERT(CHAR(10), CONVERT(DATETIME, LEFT(KYC_STATUS_CHANGED_DATE, 9), 106), 120)
+ REPLACE(SUBSTRING(KYC_STATUS_CHANGED_DATE, 10, 9), '.',':')
+ RIGHT(KYC_STATUS_CHANGED_DATE, 2);
ALTER TABLE dbo.SysData ALTER COLUMN REGISTRATION_DATE DATE;
ALTER TABLE dbo.SysData ALTER COLUMN KYC_STATUS_CHANGED_DATE DATETIME;
And then stop inserting regional and potentially problematic strings. String literals representing dates / datetimes should be:
-- date only
YYYYMMDD
-- with time:
YYYY-MM-DDThh:mm:ss.nnn
But best is to simply make sure they are date or datetime values before you ever hand them off to SQL Server. Your application should be able to do this without ever converting to some arbitrary string format. Never, ever, ever store date or datetime values as strings in SQL Server. You gain nothing and you lose quite a lot.
You need to change the data type of the column from a varchar to store it as a Date. Then when you select it you can format it any way that you like. One way to do this would be to create a new column of the correct datatype and convert the data, then remove the old column. Make sure the the old column doesn't have and foreign key relationships or you will also need to transfer those over as well.
ALTER TABLE [dbo].[SysData] ADD ConvertedDate DateTime
UPDATE [dbo].[SysData] SET ConvertedDate = CAST(VarCharDate as DateTime)
ALTER TABLE [dbo].[SysData] DROP COLUMN VarCharDate

Datetime and Integer functions on Varchar fields

We are refactoring a weird system where within its backend, values that should be stored as number and date columns, with propperly designed constraints, were stored all as varchar (using only UI validation). The thing is, while we do this the new system our ones must start to run so:
Is it possible to manipulate this varchar columns as integer for say lower or greater comparisons and, given that the dates are stored with the same format dd/MM/yyyy is it possible to treat that also varchar column as a date and use functions as: IN BETWEEN?
You could add a computed column (or a view with a column) like:
CONVERT(DATE, column_name, 103)
For performance concerns you could persist and/or index the computed column.
However if you are going to change the structure may as well just fix the data type in the first place.
Would something like this work:
SELECT Column1, Column2
FROM Table
WHERE CONVERT(datetime, DateColumn, 3) BETWEEN #StartDate AND #EndDate