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

I have 3 tables in the database that I'm working on. Out of 3, two of the tables have columns that include dates. When I checked the information schema of the columns I found that dates have the wrong data type. If you see the picture below, the highlighted columns should be stored as DATE data type.
So, I used the following query to change their data type from varchar to DATE:
ALTER TABLE [dbo].[Customer]
ALTER COLUMN DOB DATE;
ALTER TABLE [dbo].[Transactions]
ALTER COLUMN tran_date DATE;
The error that I get is:
Conversion failed when converting date and/or time from character string.
Please let me know how I can fix this error. Thanks!

What you can do is update the value using try_convert() first and then alter the column name. Note: This will set any invalid values to NULL.
update customer
set dob = try_convert(date, dob);
alter table customer alter column dbo date;
If you want to see the bad values, then before you change the table, run:
select c.*
from customer c
where try_convert(date, dob) is null and dob is not null;
You may have other ideas on how to fix the values.

You can't change from varchar to date or time or datetime by altering the column. Why? Because SQL Server does not know if the field contains '1/1/2020' or 'My dog is cute'. You will have to rebuild the table with the proper data types and then CAST() or CONVERT() the values to a true date time.
Underneath the hood, this makes more sense. A char/varchar uses one byte per character. nchar/nvarchar uses 2 bytes per character. A datetime is a number, not a character. This means you need a routine that changes this into the correct number. If you want to get deeper, the number is the number of ticks (nanoseconds) since midnight on January 1, 0001 in the Gregorian Calendar. More info.

Related

Converting all data in a Varchar column to a date format

I'm working on a table with a column, 'Expiry Date', as a varchar with all data formatted as DD/MM/YYYY.
The creator of the table has used the wrong type for this expiry date column and now the client needs to filter and show all records before and after the current date as the time. This means the type needs to be changed to date or datetime type to be able to use the CURDATE() function.
However, the current format of the values does not satisfy and wont allow the type to change unless the format is changed to YYYY-MM-DD (or similar).
Is there any way to mass format the values in this column and this column alone as there are thousands of entries and formatting one by one would be extremely time consuming.
Let me assume that you are using MySQL.
Perhaps the simplest method is to add a generated column that is a date:
alter table t add column expiry_date_date as
(str_to_date(expiry_date, '%d/%m/%Y'));
You can also fix the data:
update t
set expiry_date = str_to_date(expiry_date, '%d/%m/%Y');
This will implicitly convert the result of str_to_date() to a date, which will be in the YYYY-MM-DD format.
More importantly, you can then do:
alter table t modify column expiry_date date;
Here is a db<>fiddle.
You can do similar operations in other databases, but the exact code is a bit different.
What you need is an update on that column, but before doing it I suggest you to check if the result is what you want.
select replace(expiry_date, '/', '-') new_expiry_date
from table_name
If this returns the results you want you can run the following update:
update table_name
set expiry_date = replace(expiry_date, '/', '-')
Of course you will need to replace expiry_date and table_name with the names of your column and table.

PostgreSQL UPDATE statement treats keyword as a column

sorry for the noob question, just getting started with SQL and I have a problem that I could not resolve.
Basically, I created a table with "date of birth" column and chose wrong TYPE (integer), so every time I am trying to enter date of birth as "1998-01-04" it is just showing 1998. So, I decided to update the column to TEXT type.
Tried these queries
UPDATE users
SET date_of_birth = VARCHAR
It shows me error that there are no VARCHAR columns. Tried with as 'VARCHAR', still not working, tried as 'TEXT' and TEXT, still the same error.
What am I doing wrong?
Strings are as bad or worse than integers for this purpose. You want to use:
alter table alter column date_of_birth type date;
Note: If you have existing data in the column, you need to either use the using clause to convert it to a date. Or NULL it all out.
use this for your alter table statement
ALTER TABLE users
ALTER COLUMN date_of_birth TYPE VARCHAR(50);
I am not sure why you are storing date as varchar whereas you can store it as date, if you want to change that to date then use
ALTER TABLE users
ALTER COLUMN date_of_birth TYPE DATE;

How to order by date when a column is of type nvarchar in Microsoft SQL Server

I have an issue where I created a column sent_Date of type nvarchar while it's storing date and time.
Now when I try to sort it by date, it's not doing so correctly.
I am using this query:
select *
from tbl_skip
where sent_date > '9/27/2020 7:29:11 PM'
order by SENT_DATE desc
Like the comments have said, the real solution here is fix your design. That means changing the column's data type an nvarchar to a date and time data type, I'm going to use a datetime2(0) here, as your data is accurate to a second, so seems the most appropriate.
Firstly we need to convert the value to as ISO value. I'm also, however, going to create a new column called Bad_Sent_Date, to store values that could not be converted. Experience has taught many of us that systems that incorrectly use string data types to store dates (or numerical data) rarely have good data integrity rules on the value (because if they did, it wouldn't be an nvarchar) to start, so have bad values like '29/02/2019' or mix styles, such as having both '09/29/2020' and '29/09/2020'.
Based on the single example we have, I will assume your data is supposed to be in the format MM/dd/yy hh:mm:ss AM/PM:
ALTER TABLE dbo.tbl_skip ADD Bad_Sent_Date nvarchar(30) NULL;
GO
UPDATE TABLE dbo.tbl_skip
SET Bad_Sent_Date = CASE WHEN TRY_CONVERT(datetime2(0),Sent_date,101) IS NULL THEN Sent_date END,
Sent_Date = CONVERT(nvarchar(30),TRY_CONVERT(datetime2(0),Sent_date,101),126);
GO
Now we have an ISO format, we can change the table's data type:
ALTER TABLE dbo.tbl_skip ALTER COLUMN Sent_date datetime2(0) NULL;
Note that if you do have constraints on the column Sent_date, or it isn't NULLable, you will first need to DROP said CONSTRAINTs, change the column to be NULLable and then recreate said CONSTRAINTs after you have altered the column.
You can also review the "dates" that failed to be converted with the following:
SELECT bad_sent_date
FROM dbo.tbl_skip
WHERE bad_sent_date IS NOT NULL
AND Sent_date IS NULL;
Once that's all done, then your query simply needs an update to use an unambiguous date literal, and it'll work:
SELECT *
FROM tbl_skip
WHERE sent_date > '2020-09-27T19:29:11' --'9/27/2020 7:29:11 PM'
ORDER BY SENT_DATE DESC;
You can convert the data from string to datetime.
Please note i used 100 as an example to convert to date time. You can use below link to see if its behaving correctly. link -https://www.w3schools.com/sql/func_sqlserver_convert.asp
select *
from tbl_skip
where sent_date > convert(datetime,'9/27/2020 7:29:11 PM',100)
ORDER BY CONVERT(datetime,SENT_DATE,100) desc
You should be able to convert it to a datetime
select *
from tbl_skip
where sent_date > '9/27/2020 7:29:11 PM'
order by convert(datetime,SENT_DATE) desc
Just make sure the data in column is legit. If so, it would make sense to convert the column type to a datetime.
alter table tbl_skip alter column SENT_DATE datetime
If the data is mixed, you may need to fix it or use something like
order by try_convert(datetime,SENT_DATE) desc

tSQL - convert nvarchar(8) to time only

I am using Microsoft SQL Server Management Studio to manipulate Public transport system database.
I have a table in database named 'dbo.tblStop_times', two columns of which should be of data type time. At the moment, they are both nvarchar and they have data stored in a pattern like this - "07:39:00" (without quotes)
I had same question with date columns as well, but found a solution for that on stackoverflow just few hours back.
Below works fine for conversion of nvarchar column to date column.
ALTER TABLE tblCalendar ALTER COLUMN [start_date] DATE NOT NULL;
I am not sure if what I want is achievable or not, because the above mention conversion works just fine, I assume it might be possible.
What I have atm is - nvarchar(8), what I want it to be is sql time data type, something like hh:mm:ss [and if possible - without trailing nnnnnn - nanoseconds component]
You should be able to do:
ALTER TABLE tblStop_times ALTER COLUMN start_time TIME NOT NULL;
Here is a rextester.
EDIT:
If you don't have valid time values, then you have a problem. You should first look for the values:
select col
from tblStop_times
where try_convert(time, col) is null;
This will show you the values that cannot be converted. If you like, you can NULL them out so the alter will work:
update tblStop_times
set col = NULL
where try_convert(time, col) is null;

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