Date casting: Error when inserting but not when selecting - sql

I wrote the following query to convert 3 varchar columns into 1 datetime column:
select
MYKEY,
CAST(
CAST(YEAR AS VARCHAR(4)) +
RIGHT('0' + CAST(MONTH AS VARCHAR(2)), 2) +
RIGHT('0' + CAST(DAY AS VARCHAR(2)), 2) as DATETIME) as AD_BORN
from SOURCE
where YEAR IS NOT NULL AND MONTH IS NOT NULL AND DAY IS NOT NULL AND YEAR<>''
It works and gives me the list of expected dates.
Nevertheless, when I try to insert its results into a new table I get an error:
sql server conversion failed when converting date and/or time from
character string
This is my statement:
select
MYKEY,
CAST(
CAST(YEAR AS VARCHAR(4)) +
RIGHT('0' + CAST(MONTH AS VARCHAR(2)), 2) +
RIGHT('0' + CAST(DAY AS VARCHAR(2)), 2) as DATETIME) as AD_BORN
into MY_DATES
from SOURCE
where YEAR IS NOT NULL AND MONTH IS NOT NULL AND DAY IS NOT NULL AND YEAR<>''
MY_DATES does not exist before this query. YEAR, MONT and DAY in SOURCE are varchar (4, 2 and 2 respectively). They may contain null values.
What's wrong with that?

No need to Pad your strings. If 2012+ use try_convert()
Example
Declare #YourTable Table ([Year] varchar(50),[Month] varchar(50),[Day] varchar(50))
Insert Into #YourTable Values
(2018,1,25)
,(2018,5,55) -- Bogus Date
Select *
,AsDate = try_convert(date,[Month]+'/'+[Day]+'/'+[Year])
From #YourTable
Returns
Year Month Day AsDate
2018 1 25 2018-01-25
2018 5 55 NULL -- Bogus Date

Related

How can I convert an integer like 3212007 to date 3-21-2007 uisng IBM DB2 SQL?

The dataset I inherited has a DATE column but the values in this column are integers of the form 3212007 which should be 03-21-2007. I can't get it back into date format.
I can convert the integer to a string using CAST(myinteger as varchar(8)) without difficulty. Then I can CAST that as date by CAST(CAST(myinteger as varchar(8)) as date) which gets me a date. The problem is that my integer is formatted as 'mmddyyyy' so for 3212007, I get 3212-01-07.
select TRANSACTION_DATE from MA_NORFOLK fetch first row only;
[returns: 3212007]
select CAST(TRANSACTION_DATE as VARCHAR) from MA_NORFOLK fetch first row only;
[returns: 3212007]
select CAST(CAST(TRANSACTION_DATE as varchar(8)) as date) from MA_NORFOLK fetch first row only;
[returns: 3212-01-07]
Other posts suggest using CONVERT command, but all I get are errors
"DATE" is not valid in the context where it is used..."
Could you please advise me?
Try this:
date(to_date(digits(dec(3212007, 8)), 'MMDDYYYY'))
If you may have one digit for month, there is an alternative:
select
date
(
case when substr(char_dt, 1, 2)='00'
then translate('EFGH-0D-0C', char_dt, 'ABCDEFGH')
else translate('EFGH-AB-CD', char_dt, 'ABCDEFGH')
end
) dt, char_dt
from
(
select digits(dec(i, 8)) char_dt
from table(values 3212007, 312007) t(i)
) t;
DT CHAR_DT
---------- --------
2007-03-21 03212007
2007-01-03 00312007
This works (at least in MS SQL Server):
SELECT CAST(CONCAT( RIGHT(3212007,4),'-',
(3212007 / 1000000), '-', ((3212007 % 1000000) / 10000)) AS date)
The trick is that you don't know if you will have a single digit, or two-digit month, so you have to start with getting just the right 4 characters as the year. Then by using combinations of modulo and integer divide, you can parse out the month and day.
Of course, you will want to substitute your actual date column for the sample data that I used above.
I think this may works well:
create table #temp(
date int
)
insert into #temp (date)
values(3212007),
(12032019)
select
case when len(cast(date as varchar)) = 7
then
'0' + left(cast(date as varchar), 1) + '-' + substring(cast(date as varchar), 2,2) + '-' + right(cast(date as varchar), 4)
else left(cast(date as varchar), 2) + '-' + substring(cast(date as varchar), 3,2) + '-' + right(cast(date as varchar), 4) end
from #temp

Convert string to Datetime

I've received a flat file and after parsing and inserting it in a table. I've a column which has dates in a format yyyyMMddhhmmss
Here, yyyy is year, MM is month, dd is day, hh is hours, mm is minute and ss is seconds part
I'm trying to convert this to DateTime type as mentioned below but not working for me
SELECT CAST(StrDate as DateTime) FROM [dbo].[Mytable]
For example:
Column has a value 20150121190941 in Varchar format and it should be converted to DateTime as 2015-01-21 19:09:41.000
I apologize if it's a duplicate one.
You can use select DATETIMEFROMPARTS ( year, month, day, hour, minute, seconds, milliseconds )
declare #dt nvarchar(25) = '20150121190941'
select datetimefromparts(left(#dt,4), substring(#dt,5,2), substring(#dt,7,2),substring(#dt,9,2), substring(#dt,11,2), substring(#dt,13,2), '000')
SQL Server readily recognizes YYYYMMDD as a date. So, converting the first 8 characters to a date is easy. Alas, I don't think there is a time representation without colons.
So, here is one rather brutal method:
select (convert(datetime, left(StrDate, 8)) +
convert(time, substring(StrDate, 9, 2 ) + ':' + substring(StrDate, 11, 2 ) + ':' + substring(StrDate, 13, 2 )
)
)
Declare #dt varchar(50)
set #dt=20150121190941
create table tblDateTbl
(
col1 datetime
)
insert into dt (col1)
select SUBSTRING(#dt,1,4) + '-' + SUBSTRING(#dt,5,2) + '-' + SUBSTRING(#dt,7,2)+ ' ' + SUBSTRING(#dt,9,2)+ ':' + SUBSTRING(#dt,11,2)+ ':' + SUBSTRING(#dt,13,2)+ '.000'

How to combine two columns in sql

I have two column in sql
year month
2016 4
2014 5
What I want to do now is to combine these two columns together and get the period
Output
year month result
2016 4 201604
2014 5 201405
Are there ways to do this?
If the column data types are integer, do
select year * 100 + month from tablename
First, you need to CAST them to VARCHAR to allow concatenation. Then use RIGHT for month to pad the value with 0:
WITH Tbl AS(
SELECT 2016 AS [year], 4 AS [month] UNION ALL
SELECT 2014, 5
)
SELECT *,
CAST([year] AS VARCHAR(4)) + RIGHT('0' + CAST([month] AS VARCHAR(2)), 2)
FROM Tbl
Assuming both columns are numeric types:
SELECT year,
month,
CAST(year as char(4)) + RIGHT('00' + CAST(month as varchar(2)), 2) as result
FROM YourTable

How to convert separated Year(int), Month(int) and Day(int) columns into DateTime

Our ERP system holds year, month and day in separate int columns. I want to combine those 3 int columns into one DateTime, How can I convert it in the SQL Server.
Year | Month | Day
--------------------
2016 | 1 | 23
You could use DATEFROMPARTS(SQL Server 2012+):
SELECT DATEFROMPARTS([Year], [Month], [Day]) AS DateTim
FROM table_name
SQL Server 2008 (assuming that year is 4-digit):
SELECT CAST(CAST([year] AS VARCHAR(4)) + '-' +
CAST([month] AS VARCHAR(2)) + '-' +
CAST([day] AS VARCHAR(2))
AS DATE) AS DateTim
FROM table_name;
LiveDemo
As Gordon Linoff proposed in comment to utilize YYYYMMDD as INT to convert to DATE:
SELECT CAST(CAST([year] * 10000 + [month]*100 + [day] AS VARCHAR(8))
AS DATE) AS DateTim
FROM table_name;
LiveDemo2
Addendum
To address ypercubeᵀᴹ concerns about dateformat we could utilize ISO-8601 which is not affected by DATEFORMAT or LANGUAGE settings:
yyyy-mm-ddThh:mm:ss[.mmm]
SELECT CAST(RIGHT('000'+ CAST([year] AS VARCHAR(4)),4) + '-' +
RIGHT('0' + CAST([month] AS VARCHAR(2)),2) + '-' +
RIGHT('0' + CAST([day] AS VARCHAR(2)),2) + 'T00:00:00' AS DATE)
FROM table_name
LiveDemo3
To handle years before 1000 should be padded with zeros.
We can use SQL's CONVERT function to get Datetime value :
SELECT CONVERT(DATETIME, CONVERT(VARCHAR(2), Day) + '/' + CONVERT(VARCHAR(2), Month) + '/' + CONVERT(VARCHAR(4), Year),103) FROM Table_Name

select year(getdate() -2) and month as 12

my source table column is ReportingPeriod Nvarchar(6)
delete query has to be for datas before 2 years.
this query does not work
delete from table where ReportingPeriod < year(getdate() -2) and month as 12
I need to get 201212 as result
the criteria is current year -2 and month is 12
in 2014 expected result is 201212
in 2015 expected result is 201312
I would do all of the date maths first keeping things as datetime and then convert to nvarchar at the end. Handily, CONVERT will just truncate the result if not enough space is provided, so we just provide space for the year and month and we get what we want:
select CONVERT(nvarchar(6),
DATEADD(year,DATEDIFF(year,'20010101',CURRENT_TIMESTAMP)
,'19991201')
,112)
Result:
201212
This works because we exploit the relationship between two arbitrary dates - for instance, for any date in 2001, the result we would want would be a date in december 1999 - so that's what I've used.
It's true that the above may look overly complex for this requirement, but it's possible to make a great many problems fit the DATEADD/DATEDIFF pattern with the appropriate choice of the period to use and the two arbitrary dates and the relationship between them.
You could try something like
SELECT FROM <YOUR_TABLE>
WHERE ReportingPeriod < Convert(nvarchar(4), year(getdate()) - 2) + '12'
You could cast your ReportingPeriod to a date, so 201212 would become 2012-12-01 as I assume you aren't concerned with the day of the month.
cast(left(ReportingPeriod,4) + '-'
+ RIGHT(ReportingPeriod, 2) + '-01' as datetime)
Then take the current year -2 from GETDATE() and append the month 12 and day 31 to compare these values against, which would return 2012-12-31.
cast(cast(
cast(year(getdate()) -2 as nvarchar(4))
+ '-12-31' as nvarchar(10)) as datetime)
So combining these you should be able to select all records older than 2 years, based on the month being set to 12.
select cast(left(ReportingPeriod,4) + '-'
+ RIGHT(ReportingPeriod, 2) + '-01' as datetime) ReportPeriodDate
from [YourTable]
where cast(left(ReportingPeriod,4) + '-'
+ RIGHT(ReportingPeriod, 2) + '-01' as datetime)
<= cast(cast(
cast(year(getdate()) -2 as nvarchar(4))
+ '-12-31' as nvarchar(10)) as datetime)
Then you just need to delete with this logic.
delete [YourTable]
where cast(left(ReportingPeriod,4) + '-'
+ RIGHT(ReportingPeriod, 2) + '-01' as datetime)
<= cast(cast(
cast(year(getdate()) -2 as nvarchar(4))
+ '-12-31' as nvarchar(10)) as datetime)
Demo SQL Fiddle